ServerConfig.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:14k
- /* $Id: ServerConfig.c++,v 1.3 2007/12/06 18:19:28 faxguy Exp $ */
- /*
- * Copyright (c) 1990-1996 Sam Leffler
- * Copyright (c) 1991-1996 Silicon Graphics, Inc.
- * HylaFAX is a trademark of Silicon Graphics
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
- #include "ServerConfig.h"
- #include "FaxTrace.h"
- #include "DialRules.h"
- #include "UUCPLock.h"
- #include "REArray.h"
- #include "BoolArray.h"
- #include "faxApp.h"
- #include <ctype.h>
- #include "Sys.h"
- #include "config.h"
- ServerConfig::ServerConfig()
- {
- lastTSIModTime = 0;
- lastPWDModTime = 0;
- tsiPats = NULL;
- pwdPats = NULL;
- acceptTSI = NULL;
- acceptPWD = NULL;
- dialRules = NULL;
- setupConfig();
- }
- ServerConfig::~ServerConfig()
- {
- delete dialRules;
- delete acceptTSI;
- delete acceptPWD;
- delete tsiPats;
- delete pwdPats;
- }
- void
- ServerConfig::configError(const char* fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- vconfigError(fmt, ap);
- va_end(ap);
- }
- void
- ServerConfig::configTrace(const char* fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- vconfigTrace(fmt, ap);
- va_end(ap);
- }
- #define N(a) (sizeof (a) / sizeof (a[0]))
- ServerConfig::S_booltag ServerConfig::bools[] = {
- { "batchlogs", &ServerConfig::batchLogs, true },
- { "polllockpokemodem", &ServerConfig::pollLockPokeModem, false },
- };
- ServerConfig::S_stringtag ServerConfig::strings[] = {
- { "logfacility", &ServerConfig::logFacility, LOG_FAX },
- { "faxnumber", &ServerConfig::FAXNumber },
- { "areacode", &ServerConfig::areaCode },
- { "countrycode", &ServerConfig::countryCode },
- { "longdistanceprefix", &ServerConfig::longDistancePrefix },
- { "internationalprefix",&ServerConfig::internationalPrefix },
- { "qualifytsi", &ServerConfig::qualifyTSI },
- { "qualifypwd", &ServerConfig::qualifyPWD },
- { "uucplockdir", &ServerConfig::uucpLockDir, UUCP_LOCKDIR },
- { "uucplocktype", &ServerConfig::uucpLockType, UUCP_LOCKTYPE },
- };
- ServerConfig::S_numbertag ServerConfig::numbers[] = {
- { "tracingmask", &ServerConfig::tracingMask, // NB: must be first
- FAXTRACE_MODEMIO|FAXTRACE_TIMEOUTS },
- { "sessiontracing", &ServerConfig::logTracingLevel, 0xFFF },
- { "servertracing", &ServerConfig::tracingLevel, FAXTRACE_SERVER },
- { "uucplocktimeout", &ServerConfig::uucpLockTimeout, 0 },
- { "jobreqproto", &ServerConfig::requeueProto, FAX_REQPROTO },
- { "jobreqother", &ServerConfig::requeueOther, FAX_REQUEUE },
- { "jobretryother", &ServerConfig::retryOther, FAX_RETRY },
- { "pollmodemwait", &ServerConfig::pollModemWait, 30 },
- { "polllockwait", &ServerConfig::pollLockWait, 30 },
- { "maxrecvpages", &ServerConfig::maxRecvPages, (u_int) -1 },
- { "maxbadcalls", &ServerConfig::maxConsecutiveBadCalls, 25 },
- { "maxsetupattempts", &ServerConfig::maxSetupAttempts, 2 },
- };
- ServerConfig::S_filemodetag ServerConfig::filemodes[] = {
- { "recvfilemode", &ServerConfig::recvFileMode, 0600 },
- { "devicemode", &ServerConfig::deviceMode, 0600 },
- { "logfilemode", &ServerConfig::logMode, 0600 },
- { "uucplockmode", &ServerConfig::uucpLockMode, UUCP_LOCKMODE },
- };
- void
- ServerConfig::setupConfig()
- {
- int i;
- for (i = N(bools)-1; i >= 0; i--)
- (*this).*bools[i].p = bools[i].def;
- for (i = N(strings)-1; i >= 0; i--)
- (*this).*strings[i].p = (strings[i].def ? strings[i].def : "");
- for (i = N(filemodes)-1; i >= 0; i--)
- (*this).*filemodes[i].p = (mode_t) filemodes[i].def;
- for (i = N(numbers)-1; i >= 0; i--)
- (*this).*numbers[i].p = numbers[i].def;
- speakerVolume = ClassModem::QUIET; // default speaker volume
- #ifdef sgi
- clocalAsRoot = true; // under IRIX must be root to set CLOCAL
- #else
- clocalAsRoot = false; // everywhere else anyone can do it
- #endif
- #if HAS_SCHEDCTL || HAS_PRIOCNTL || HAS_RTPRIO
- priorityScheduling = true; // maintain historic behavior
- #else
- priorityScheduling = false; // for new mechanisms anyone can do it
- #endif
- requeueTTS[ClassModem::OK] = 0;
- requeueTTS[ClassModem::BUSY] = FAX_REQBUSY;
- requeueTTS[ClassModem::NOCARRIER] = FAX_REQUEUE;
- requeueTTS[ClassModem::NOANSWER] = FAX_REQUEUE;
- requeueTTS[ClassModem::NODIALTONE] = FAX_REQUEUE;
- requeueTTS[ClassModem::ERROR] = FAX_REQUEUE;
- requeueTTS[ClassModem::FAILURE] = FAX_REQUEUE;
- requeueTTS[ClassModem::NOFCON] = FAX_REQUEUE;
- requeueTTS[ClassModem::DATACONN] = FAX_REQUEUE;
- retryMAX[ClassModem::OK] = 0;
- retryMAX[ClassModem::BUSY] = FAX_RETBUSY;
- retryMAX[ClassModem::NOCARRIER] = 1; // Old NoCarrierRetry Default
- retryMAX[ClassModem::NOANSWER] = FAX_RETRY;
- retryMAX[ClassModem::NODIALTONE] = FAX_RETRY;
- retryMAX[ClassModem::ERROR] = FAX_RETRY;
- retryMAX[ClassModem::FAILURE] = FAX_RETRY;
- retryMAX[ClassModem::NOFCON] = FAX_RETRY;
- retryMAX[ClassModem::DATACONN] = FAX_RETRY;
- localIdentifier = "";
- delete dialRules, dialRules = NULL;
- }
- void
- ServerConfig::resetConfig()
- {
- ModemConfig::resetConfig();
- setupConfig();
- }
- #define valeq(a,b) (strcasecmp(a,b)==0)
- SpeakerVolume
- ServerConfig::getVolume(const char* cp)
- {
- if (valeq(cp, "off"))
- return ClassModem::OFF;
- else if (valeq(cp, "quiet"))
- return ClassModem::QUIET;
- else if (valeq(cp, "low"))
- return ClassModem::LOW;
- else if (valeq(cp, "medium"))
- return ClassModem::MEDIUM;
- else if (valeq(cp, "high"))
- return ClassModem::HIGH;
- else {
- configError("Unknown speaker volume "%s"; using "quiet"", cp);
- return ClassModem::QUIET;
- }
- }
- void
- ServerConfig::setLocalIdentifier(const fxStr& lid)
- {
- localIdentifier = lid;
- }
- void
- ServerConfig::setModemSpeakerVolume(SpeakerVolume level)
- {
- speakerVolume = level;
- }
- /*
- * Subclass DialStringRules so that we can redirect the
- * diagnostic and tracing interfaces through the server.
- */
- class ServerConfigDialStringRules : public DialStringRules {
- private:
- ServerConfig& config; // XXX should be const, but requires other mods
- virtual void parseError(const char* fmt ...);
- virtual void traceParse(const char* fmt ...);
- virtual void traceRules(const char* fmt ...);
- public:
- ServerConfigDialStringRules(ServerConfig& config, const char* filename);
- ~ServerConfigDialStringRules();
- };
- ServerConfigDialStringRules::ServerConfigDialStringRules(ServerConfig& c, const char* f)
- : DialStringRules(f), config(c)
- {}
- ServerConfigDialStringRules::~ServerConfigDialStringRules() {}
- void
- ServerConfigDialStringRules::parseError(const char* fmt ...)
- {
- va_list ap;
- va_start(ap, fmt);
- config.vconfigError(fmt, ap);
- va_end(ap);
- }
- void
- ServerConfigDialStringRules::traceParse(const char* fmt ...)
- {
- va_list ap;
- va_start(ap, fmt);
- config.vdialrulesTrace(fmt, ap);
- va_end(ap);
- }
- void
- ServerConfigDialStringRules::traceRules(const char* fmt ...)
- {
- va_list ap;
- va_start(ap, fmt);
- config.vdialrulesTrace(fmt, ap);
- va_end(ap);
- }
- void
- ServerConfig::setDialRules(const char* name)
- {
- delete dialRules;
- dialRules = new ServerConfigDialStringRules(*this, name);
- dialRules->setVerbose(
- ((tracingLevel|logTracingLevel) & FAXTRACE_DIALRULES) != 0);
- /*
- * Setup configuration environment.
- */
- dialRules->def("AreaCode", areaCode);
- dialRules->def("CountryCode", countryCode);
- dialRules->def("LongDistancePrefix", longDistancePrefix);
- dialRules->def("InternationalPrefix", internationalPrefix);
- if (!dialRules->parse()) {
- configError("Parse error in dial string rules "%s"", name);
- delete dialRules, dialRules = NULL;
- }
- }
- /*
- * Convert a dialing string to a canonical format.
- */
- fxStr
- ServerConfig::canonicalizePhoneNumber(const fxStr& ds)
- {
- if (dialRules)
- return dialRules->canonicalNumber(ds);
- else
- return ds;
- }
- /*
- * Prepare a dialing string for use.
- */
- fxStr
- ServerConfig::prepareDialString(const fxStr& ds)
- {
- if (dialRules)
- return dialRules->dialString(ds);
- else
- return ds;
- }
- /*
- * Create an appropriate UUCP lock instance.
- */
- UUCPLock*
- ServerConfig::getUUCPLock(const fxStr& deviceName)
- {
- return UUCPLock::newLock(uucpLockType,
- uucpLockDir, deviceName, uucpLockMode);
- }
- bool
- ServerConfig::checkACL(const fxStr& id, REArray* pats, fxBoolArray& accept)
- {
- if (pats != NULL) {
- for (u_int i = 0; i < pats->length(); i++)
- if ((*pats)[i]->Find(id))
- return (accept[i]);
- }
- return (false); // NB: reject if no patterns!
- }
- bool
- ServerConfig::isTSIOk(const fxStr& tsi)
- {
- updatePatterns(qualifyTSI, tsiPats, acceptTSI, lastTSIModTime);
- return (qualifyTSI == "" ? true : checkACL(tsi, tsiPats, *acceptTSI));
- }
- bool
- ServerConfig::isPWDOk(const fxStr& pwd)
- {
- updatePatterns(qualifyPWD, pwdPats, acceptPWD, lastPWDModTime);
- return (qualifyPWD == "" ? true : checkACL(pwd, pwdPats, *acceptPWD));
- }
- /*
- * Update pattern arrays if a file patterns has
- * been changed since the last time we read it.
- */
- void
- ServerConfig::updatePatterns(const fxStr& file,
- REArray*& pats, fxBoolArray*& accept,
- time_t& lastModTime)
- {
- struct stat sb;
- if (file != "" && Sys::stat(file, sb) >= 0 && sb.st_mtime >= lastModTime) {
- FILE* fp = Sys::fopen(file, "r");
- if (fp != NULL) {
- readPatterns(fp, pats, accept);
- lastModTime = sb.st_mtime;
- fclose(fp);
- }
- } else if (pats) {
- // file's been removed, delete any existing info
- delete pats, pats = NULL;
- delete accept, accept = NULL;
- }
- }
- /*
- * Read the file of patterns into an array.
- *
- * The order of patterns is preserved and a leading ``!''
- * is interpreted to mean ``reject if matched by this
- * regex''. Note also that we always allocate an array
- * of patterns. The pattern matching logic rejects
- * things that don't match any patterns. Thus an empty file
- * causes all incoming facsimile to be rejected.
- */
- void
- ServerConfig::readPatterns(FILE* fp, REArray*& pats, fxBoolArray*& accept)
- {
- if (pats)
- pats->resize(0);
- else
- pats = new REArray;
- if (accept)
- accept->resize(0);
- else
- accept = new fxBoolArray;
- char line[256];
- while (fgets(line, sizeof (line)-1, fp)) {
- char* cp = strchr(line, '#');
- if (cp || (cp = strchr(line, 'n')))
- *cp = ' ';
- /* trim off trailing white space */
- for (cp = strchr(line, ' '); cp > line; cp--)
- if (!isspace(cp[-1]))
- break;
- *cp = ' ';
- if (line[0] == ' ')
- continue;
- RE* re;
- if (line[0] == '!') {
- accept->append(false);
- pats->append(re = new RE(line+1));
- } else {
- accept->append(true);
- pats->append(re = new RE(line));
- }
- if (re->getErrorCode() > REG_NOMATCH) {
- fxStr emsg;
- re->getError(emsg);
- configError("Bad TSI/CID pattern: %s: " | emsg, re->pattern());
- }
- }
- }
- static void
- tiffErrorHandler(const char* module, const char* fmt0, va_list ap)
- {
- fxStr fmt = (module != NULL) ?
- fxStr::format("%s: Warnings, %s.", module, fmt0)
- : fxStr::format("Warnings, %s.", fmt0);
- vlogError(fmt, ap);
- }
- static void
- tiffWarningHandler(const char* module, const char* fmt0, va_list ap)
- {
- fxStr fmt = (module != NULL) ?
- fxStr::format("%s: Warnings, %s.", module, fmt0)
- : fxStr::format("Warnings, %s.", fmt0);
- vlogWarning(fmt, ap);
- }
- bool
- ServerConfig::setConfigItem(const char* tag, const char* value)
- {
- u_int ix;
- if (findTag(tag, (const tags*)strings, N(strings), ix)) {
- (*this).*strings[ix].p = value;
- switch (ix) {
- case 0: faxApp::setLogFacility(logFacility); break;
- }
- } else if (findTag(tag, (const tags*)numbers, N(numbers), ix)) {
- (*this).*numbers[ix].p = getNumber(value);
- switch (ix) {
- case 1: tracingLevel &= ~tracingMask;
- case 2: logTracingLevel &= ~tracingMask;
- if (dialRules)
- dialRules->setVerbose(
- (tracingLevel|logTracingLevel) & FAXTRACE_DIALRULES);
- if ((tracingLevel|logTracingLevel) & FAXTRACE_TIFF) {
- TIFFSetErrorHandler(tiffErrorHandler);
- TIFFSetWarningHandler(tiffWarningHandler);
- } else {
- TIFFSetErrorHandler(NULL);
- TIFFSetWarningHandler(NULL);
- }
- break;
- case 3: UUCPLock::setLockTimeout(uucpLockTimeout); break;
- }
- } else if (findTag(tag, (const tags*)filemodes, N(filemodes), ix))
- (*this).*filemodes[ix].p = strtol(value, 0, 8);
- else if (findTag(tag, (const tags*)bools, N(bools), ix))
- (*this).*bools[ix].p = getBoolean(value);
- else if (streq(tag, "speakervolume"))
- setModemSpeakerVolume(getVolume(value));
- else if (streq(tag, "localidentifier"))
- setLocalIdentifier(value);
- else if (streq(tag, "dialstringrules"))
- setDialRules(value);
- else if (streq(tag, "clocalasroot"))
- clocalAsRoot = getBoolean(value);
- else if (streq(tag, "priorityscheduling"))
- priorityScheduling = getBoolean(value);
- else if (streq(tag, "jobreqbusy"))
- requeueTTS[ClassModem::BUSY] = getNumber(value);
- else if (streq(tag, "jobreqnocarrier"))
- requeueTTS[ClassModem::NOCARRIER] = getNumber(value);
- else if (streq(tag, "jobreqnoanswer"))
- requeueTTS[ClassModem::NOANSWER] = getNumber(value);
- else if (streq(tag, "jobreqnofcon"))
- requeueTTS[ClassModem::NOFCON] = getNumber(value);
- else if (streq(tag, "jobreqdataconn"))
- requeueTTS[ClassModem::DATACONN] = getNumber(value);
- else if (streq(tag, "nocarrierretrys"))
- retryMAX[ClassModem::NOCARRIER] = getNumber(value);
- else if (streq(tag, "jobretrybusy"))
- retryMAX[ClassModem::BUSY] = getNumber(value);
- else if (streq(tag, "jobretrynocarrier"))
- retryMAX[ClassModem::NOCARRIER] = getNumber(value);
- else if (streq(tag, "jobretrynoanswer"))
- retryMAX[ClassModem::NOANSWER] = getNumber(value);
- else if (streq(tag, "jobretrynofcon"))
- retryMAX[ClassModem::NOFCON] = getNumber(value);
- else if (streq(tag, "jobretrydataconn"))
- retryMAX[ClassModem::DATACONN] = getNumber(value);
- else
- return ModemConfig::setConfigItem(tag, value);
- return (true);
- }
- #undef N