ServerConfig.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:14k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: ServerConfig.c++,v 1.3 2007/12/06 18:19:28 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. #include "ServerConfig.h"
  27. #include "FaxTrace.h"
  28. #include "DialRules.h"
  29. #include "UUCPLock.h"
  30. #include "REArray.h"
  31. #include "BoolArray.h"
  32. #include "faxApp.h"
  33. #include <ctype.h>
  34. #include "Sys.h"
  35. #include "config.h"
  36. ServerConfig::ServerConfig()
  37. {
  38.     lastTSIModTime = 0;
  39.     lastPWDModTime = 0;
  40.     tsiPats = NULL;
  41.     pwdPats = NULL;
  42.     acceptTSI = NULL;
  43.     acceptPWD = NULL;
  44.     dialRules = NULL;
  45.     setupConfig();
  46. }
  47. ServerConfig::~ServerConfig()
  48. {
  49.     delete dialRules;
  50.     delete acceptTSI;
  51.     delete acceptPWD;
  52.     delete tsiPats;
  53.     delete pwdPats;
  54. }
  55. void
  56. ServerConfig::configError(const char* fmt, ...)
  57. {
  58.     va_list ap;
  59.     va_start(ap, fmt);
  60.     vconfigError(fmt, ap);
  61.     va_end(ap);
  62. }
  63. void
  64. ServerConfig::configTrace(const char* fmt, ...)
  65. {
  66.     va_list ap;
  67.     va_start(ap, fmt);
  68.     vconfigTrace(fmt, ap);
  69.     va_end(ap);
  70. }
  71. #define N(a) (sizeof (a) / sizeof (a[0]))
  72. ServerConfig::S_booltag ServerConfig::bools[] = {
  73. { "batchlogs", &ServerConfig::batchLogs, true },
  74. { "polllockpokemodem", &ServerConfig::pollLockPokeModem, false },
  75. };
  76. ServerConfig::S_stringtag ServerConfig::strings[] = {
  77. { "logfacility", &ServerConfig::logFacility, LOG_FAX },
  78. { "faxnumber", &ServerConfig::FAXNumber },
  79. { "areacode", &ServerConfig::areaCode },
  80. { "countrycode", &ServerConfig::countryCode },
  81. { "longdistanceprefix", &ServerConfig::longDistancePrefix },
  82. { "internationalprefix",&ServerConfig::internationalPrefix },
  83. { "qualifytsi", &ServerConfig::qualifyTSI },
  84. { "qualifypwd", &ServerConfig::qualifyPWD },
  85. { "uucplockdir", &ServerConfig::uucpLockDir, UUCP_LOCKDIR },
  86. { "uucplocktype", &ServerConfig::uucpLockType, UUCP_LOCKTYPE },
  87. };
  88. ServerConfig::S_numbertag ServerConfig::numbers[] = {
  89. { "tracingmask", &ServerConfig::tracingMask, // NB: must be first
  90.    FAXTRACE_MODEMIO|FAXTRACE_TIMEOUTS },
  91. { "sessiontracing", &ServerConfig::logTracingLevel, 0xFFF },
  92. { "servertracing", &ServerConfig::tracingLevel, FAXTRACE_SERVER },
  93. { "uucplocktimeout", &ServerConfig::uucpLockTimeout, 0 },
  94. { "jobreqproto", &ServerConfig::requeueProto, FAX_REQPROTO },
  95. { "jobreqother", &ServerConfig::requeueOther, FAX_REQUEUE },
  96. { "jobretryother", &ServerConfig::retryOther, FAX_RETRY },
  97. { "pollmodemwait", &ServerConfig::pollModemWait, 30 },
  98. { "polllockwait", &ServerConfig::pollLockWait, 30 },
  99. { "maxrecvpages", &ServerConfig::maxRecvPages, (u_int) -1 },
  100. { "maxbadcalls", &ServerConfig::maxConsecutiveBadCalls, 25 },
  101. { "maxsetupattempts", &ServerConfig::maxSetupAttempts, 2 },
  102. };
  103. ServerConfig::S_filemodetag ServerConfig::filemodes[] = {
  104. { "recvfilemode", &ServerConfig::recvFileMode, 0600 },
  105. { "devicemode", &ServerConfig::deviceMode, 0600 },
  106. { "logfilemode", &ServerConfig::logMode, 0600 },
  107. { "uucplockmode", &ServerConfig::uucpLockMode, UUCP_LOCKMODE },
  108. };
  109. void
  110. ServerConfig::setupConfig()
  111. {
  112.     int i;
  113.     for (i = N(bools)-1; i >= 0; i--)
  114. (*this).*bools[i].p = bools[i].def;
  115.     for (i = N(strings)-1; i >= 0; i--)
  116. (*this).*strings[i].p = (strings[i].def ? strings[i].def : "");
  117.     for (i = N(filemodes)-1; i >= 0; i--)
  118. (*this).*filemodes[i].p = (mode_t) filemodes[i].def;
  119.     for (i = N(numbers)-1; i >= 0; i--)
  120. (*this).*numbers[i].p = numbers[i].def;
  121.     speakerVolume = ClassModem::QUIET; // default speaker volume
  122. #ifdef sgi
  123.     clocalAsRoot = true; // under IRIX must be root to set CLOCAL
  124. #else
  125.     clocalAsRoot = false; // everywhere else anyone can do it
  126. #endif
  127. #if HAS_SCHEDCTL || HAS_PRIOCNTL || HAS_RTPRIO
  128.     priorityScheduling = true; // maintain historic behavior
  129. #else
  130.     priorityScheduling = false; // for new mechanisms anyone can do it
  131. #endif
  132.     requeueTTS[ClassModem::OK] = 0;
  133.     requeueTTS[ClassModem::BUSY] = FAX_REQBUSY;
  134.     requeueTTS[ClassModem::NOCARRIER] = FAX_REQUEUE;
  135.     requeueTTS[ClassModem::NOANSWER] = FAX_REQUEUE;
  136.     requeueTTS[ClassModem::NODIALTONE] = FAX_REQUEUE;
  137.     requeueTTS[ClassModem::ERROR] = FAX_REQUEUE;
  138.     requeueTTS[ClassModem::FAILURE] = FAX_REQUEUE;
  139.     requeueTTS[ClassModem::NOFCON] = FAX_REQUEUE;
  140.     requeueTTS[ClassModem::DATACONN] = FAX_REQUEUE;
  141.     retryMAX[ClassModem::OK] = 0;
  142.     retryMAX[ClassModem::BUSY] = FAX_RETBUSY;
  143.     retryMAX[ClassModem::NOCARRIER] = 1; // Old NoCarrierRetry Default
  144.     retryMAX[ClassModem::NOANSWER] = FAX_RETRY;
  145.     retryMAX[ClassModem::NODIALTONE] = FAX_RETRY;
  146.     retryMAX[ClassModem::ERROR] = FAX_RETRY;
  147.     retryMAX[ClassModem::FAILURE] = FAX_RETRY;
  148.     retryMAX[ClassModem::NOFCON] = FAX_RETRY;
  149.     retryMAX[ClassModem::DATACONN] = FAX_RETRY;
  150.     localIdentifier = "";
  151.     delete dialRules, dialRules = NULL;
  152. }
  153. void
  154. ServerConfig::resetConfig()
  155. {
  156.     ModemConfig::resetConfig();
  157.     setupConfig();
  158. }
  159. #define valeq(a,b) (strcasecmp(a,b)==0)
  160. SpeakerVolume
  161. ServerConfig::getVolume(const char* cp)
  162. {
  163.     if (valeq(cp, "off"))
  164. return ClassModem::OFF;
  165.     else if (valeq(cp, "quiet"))
  166. return ClassModem::QUIET;
  167.     else if (valeq(cp, "low"))
  168. return ClassModem::LOW;
  169.     else if (valeq(cp, "medium"))
  170. return ClassModem::MEDIUM;
  171.     else if (valeq(cp, "high"))
  172. return ClassModem::HIGH;
  173.     else {
  174. configError("Unknown speaker volume "%s"; using "quiet"", cp);
  175. return ClassModem::QUIET;
  176.     }
  177. }
  178. void
  179. ServerConfig::setLocalIdentifier(const fxStr& lid)
  180. {
  181.     localIdentifier = lid;
  182. }
  183. void
  184. ServerConfig::setModemSpeakerVolume(SpeakerVolume level)
  185. {
  186.     speakerVolume = level;
  187. }
  188. /*
  189.  * Subclass DialStringRules so that we can redirect the
  190.  * diagnostic and tracing interfaces through the server.
  191.  */
  192. class ServerConfigDialStringRules : public DialStringRules {
  193. private:
  194.     ServerConfig& config; // XXX should be const, but requires other mods
  195.     virtual void parseError(const char* fmt ...);
  196.     virtual void traceParse(const char* fmt ...);
  197.     virtual void traceRules(const char* fmt ...);
  198. public:
  199.     ServerConfigDialStringRules(ServerConfig& config, const char* filename);
  200.     ~ServerConfigDialStringRules();
  201. };
  202. ServerConfigDialStringRules::ServerConfigDialStringRules(ServerConfig& c, const char* f)
  203.     : DialStringRules(f), config(c)
  204. {}
  205. ServerConfigDialStringRules::~ServerConfigDialStringRules() {}
  206. void
  207. ServerConfigDialStringRules::parseError(const char* fmt ...)
  208. {
  209.     va_list ap;
  210.     va_start(ap, fmt);
  211.     config.vconfigError(fmt, ap);
  212.     va_end(ap);
  213. }
  214. void
  215. ServerConfigDialStringRules::traceParse(const char* fmt ...)
  216. {
  217.     va_list ap;
  218.     va_start(ap, fmt);
  219.     config.vdialrulesTrace(fmt, ap);
  220.     va_end(ap);
  221. }
  222. void
  223. ServerConfigDialStringRules::traceRules(const char* fmt ...)
  224. {
  225.     va_list ap;
  226.     va_start(ap, fmt);
  227.     config.vdialrulesTrace(fmt, ap);
  228.     va_end(ap);
  229. }
  230. void
  231. ServerConfig::setDialRules(const char* name)
  232. {
  233.     delete dialRules;
  234.     dialRules = new ServerConfigDialStringRules(*this, name);
  235.     dialRules->setVerbose(
  236. ((tracingLevel|logTracingLevel) & FAXTRACE_DIALRULES) != 0);
  237.     /*
  238.      * Setup configuration environment.
  239.      */
  240.     dialRules->def("AreaCode", areaCode);
  241.     dialRules->def("CountryCode", countryCode);
  242.     dialRules->def("LongDistancePrefix", longDistancePrefix);
  243.     dialRules->def("InternationalPrefix", internationalPrefix);
  244.     if (!dialRules->parse()) {
  245. configError("Parse error in dial string rules "%s"", name);
  246. delete dialRules, dialRules = NULL;
  247.     }
  248. }
  249. /*
  250.  * Convert a dialing string to a canonical format.
  251.  */
  252. fxStr
  253. ServerConfig::canonicalizePhoneNumber(const fxStr& ds)
  254. {
  255.     if (dialRules)
  256. return dialRules->canonicalNumber(ds);
  257.     else
  258. return ds;
  259. }
  260. /*
  261.  * Prepare a dialing string for use.
  262.  */
  263. fxStr
  264. ServerConfig::prepareDialString(const fxStr& ds)
  265. {
  266.     if (dialRules)
  267. return dialRules->dialString(ds);
  268.     else
  269. return ds;
  270. }
  271. /*
  272.  * Create an appropriate UUCP lock instance.
  273.  */
  274. UUCPLock*
  275. ServerConfig::getUUCPLock(const fxStr& deviceName)
  276. {
  277.     return UUCPLock::newLock(uucpLockType,
  278. uucpLockDir, deviceName, uucpLockMode);
  279. }
  280. bool
  281. ServerConfig::checkACL(const fxStr& id, REArray* pats, fxBoolArray& accept)
  282. {
  283.     if (pats != NULL) {
  284. for (u_int i = 0; i < pats->length(); i++)
  285.     if ((*pats)[i]->Find(id))
  286. return (accept[i]);
  287.     }
  288.     return (false); // NB: reject if no patterns!
  289. }
  290. bool
  291. ServerConfig::isTSIOk(const fxStr& tsi)
  292. {
  293.     updatePatterns(qualifyTSI, tsiPats, acceptTSI, lastTSIModTime);
  294.     return (qualifyTSI == "" ? true : checkACL(tsi, tsiPats, *acceptTSI));
  295. }
  296. bool
  297. ServerConfig::isPWDOk(const fxStr& pwd)
  298. {
  299.     updatePatterns(qualifyPWD, pwdPats, acceptPWD, lastPWDModTime);
  300.     return (qualifyPWD == "" ? true : checkACL(pwd, pwdPats, *acceptPWD));
  301. }
  302. /*
  303.  * Update pattern arrays if a file patterns has
  304.  * been changed since the last time we read it.
  305.  */
  306. void
  307. ServerConfig::updatePatterns(const fxStr& file,
  308.     REArray*& pats, fxBoolArray*& accept,
  309.     time_t& lastModTime)
  310. {
  311.     struct stat sb;
  312.     if (file != "" && Sys::stat(file, sb) >= 0 && sb.st_mtime >= lastModTime) {
  313. FILE* fp = Sys::fopen(file, "r");
  314. if (fp != NULL) {
  315.     readPatterns(fp, pats, accept);
  316.     lastModTime = sb.st_mtime;
  317.     fclose(fp);
  318. }
  319.     } else if (pats) {
  320. // file's been removed, delete any existing info
  321. delete pats, pats = NULL;
  322. delete accept, accept = NULL;
  323.     }
  324. }
  325. /*
  326.  * Read the file of patterns into an array.
  327.  *
  328.  * The order of patterns is preserved and a leading ``!''
  329.  * is interpreted to mean ``reject if matched by this
  330.  * regex''.  Note also that we always allocate an array
  331.  * of patterns.  The pattern matching logic rejects
  332.  * things that don't match any patterns.  Thus an empty file
  333.  * causes all incoming facsimile to be rejected.
  334.  */
  335. void
  336. ServerConfig::readPatterns(FILE* fp, REArray*& pats, fxBoolArray*& accept)
  337. {
  338.     if (pats)
  339. pats->resize(0);
  340.     else
  341. pats = new REArray;
  342.     if (accept)
  343. accept->resize(0);
  344.     else
  345. accept = new fxBoolArray;
  346.     char line[256];
  347.     while (fgets(line, sizeof (line)-1, fp)) {
  348. char* cp = strchr(line, '#');
  349. if (cp || (cp = strchr(line, 'n')))
  350.     *cp = '';
  351. /* trim off trailing white space */
  352. for (cp = strchr(line, ''); cp > line; cp--)
  353.     if (!isspace(cp[-1]))
  354. break;
  355. *cp = '';
  356. if (line[0] == '')
  357.     continue;
  358. RE* re;
  359. if (line[0] == '!') {
  360.     accept->append(false);
  361.     pats->append(re = new RE(line+1));
  362. } else {
  363.     accept->append(true);
  364.     pats->append(re = new RE(line));
  365. }
  366. if (re->getErrorCode() > REG_NOMATCH) {
  367.     fxStr emsg;
  368.     re->getError(emsg);
  369.     configError("Bad TSI/CID pattern: %s: " | emsg, re->pattern());
  370. }
  371.     }
  372. }
  373. static void
  374. tiffErrorHandler(const char* module, const char* fmt0, va_list ap)
  375. {
  376.     fxStr fmt = (module != NULL) ?
  377.         fxStr::format("%s: Warnings, %s.", module, fmt0)
  378.         : fxStr::format("Warnings, %s.", fmt0);
  379.     vlogError(fmt, ap);
  380. }
  381. static void
  382. tiffWarningHandler(const char* module, const char* fmt0, va_list ap)
  383. {
  384.     fxStr fmt = (module != NULL) ?
  385.         fxStr::format("%s: Warnings, %s.", module, fmt0)
  386.         : fxStr::format("Warnings, %s.", fmt0);
  387.     vlogWarning(fmt, ap);
  388. }
  389. bool
  390. ServerConfig::setConfigItem(const char* tag, const char* value)
  391. {
  392.     u_int ix;
  393.     if (findTag(tag, (const tags*)strings, N(strings), ix)) {
  394. (*this).*strings[ix].p = value;
  395. switch (ix) {
  396. case 0: faxApp::setLogFacility(logFacility); break;
  397. }
  398.     } else if (findTag(tag, (const tags*)numbers, N(numbers), ix)) {
  399. (*this).*numbers[ix].p = getNumber(value);
  400. switch (ix) {
  401. case 1: tracingLevel &= ~tracingMask;
  402. case 2: logTracingLevel &= ~tracingMask;
  403.     if (dialRules)
  404. dialRules->setVerbose(
  405.     (tracingLevel|logTracingLevel) & FAXTRACE_DIALRULES);
  406.     if ((tracingLevel|logTracingLevel) & FAXTRACE_TIFF) {
  407. TIFFSetErrorHandler(tiffErrorHandler);
  408. TIFFSetWarningHandler(tiffWarningHandler);
  409.     } else {
  410. TIFFSetErrorHandler(NULL);
  411. TIFFSetWarningHandler(NULL);
  412.     }
  413.     break;
  414. case 3: UUCPLock::setLockTimeout(uucpLockTimeout); break;
  415. }
  416.     } else if (findTag(tag, (const tags*)filemodes, N(filemodes), ix))
  417. (*this).*filemodes[ix].p = strtol(value, 0, 8);
  418.     else if (findTag(tag, (const tags*)bools, N(bools), ix))
  419. (*this).*bools[ix].p = getBoolean(value);
  420.     else if (streq(tag, "speakervolume"))
  421. setModemSpeakerVolume(getVolume(value));
  422.     else if (streq(tag, "localidentifier"))
  423. setLocalIdentifier(value);
  424.     else if (streq(tag, "dialstringrules"))
  425. setDialRules(value);
  426.     else if (streq(tag, "clocalasroot"))
  427. clocalAsRoot = getBoolean(value);
  428.     else if (streq(tag, "priorityscheduling"))
  429. priorityScheduling = getBoolean(value);
  430.     else if (streq(tag, "jobreqbusy"))
  431. requeueTTS[ClassModem::BUSY] = getNumber(value);
  432.     else if (streq(tag, "jobreqnocarrier"))
  433. requeueTTS[ClassModem::NOCARRIER] = getNumber(value);
  434.     else if (streq(tag, "jobreqnoanswer"))
  435. requeueTTS[ClassModem::NOANSWER] = getNumber(value);
  436.     else if (streq(tag, "jobreqnofcon"))
  437. requeueTTS[ClassModem::NOFCON] = getNumber(value);
  438.     else if (streq(tag, "jobreqdataconn"))
  439. requeueTTS[ClassModem::DATACONN] = getNumber(value);
  440.     else if (streq(tag, "nocarrierretrys"))
  441. retryMAX[ClassModem::NOCARRIER] = getNumber(value);
  442.     else if (streq(tag, "jobretrybusy"))
  443. retryMAX[ClassModem::BUSY] = getNumber(value);
  444.     else if (streq(tag, "jobretrynocarrier"))
  445. retryMAX[ClassModem::NOCARRIER] = getNumber(value);
  446.     else if (streq(tag, "jobretrynoanswer"))
  447. retryMAX[ClassModem::NOANSWER] = getNumber(value);
  448.     else if (streq(tag, "jobretrynofcon"))
  449. retryMAX[ClassModem::NOFCON] = getNumber(value);
  450.     else if (streq(tag, "jobretrydataconn"))
  451. retryMAX[ClassModem::DATACONN] = getNumber(value);
  452.     else
  453. return ModemConfig::setConfigItem(tag, value);
  454.     return (true);
  455. }
  456. #undef N