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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: HylaFAXServer.c++,v 1.14 2009/09/29 11:10:13 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1995-1996 Sam Leffler
  4.  * Copyright (c) 1995-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 "port.h"
  27. #include "Sys.h"
  28. #include "config.h"
  29. #include "tiffio.h"
  30. #include "HylaFAXServer.h"
  31. #include "Dispatcher.h"
  32. #include "StackBuffer.h"
  33. #include "Sequence.h"
  34. #include <ctype.h>
  35. #include <sys/file.h>
  36. #include <pwd.h>
  37. #include <limits.h>
  38. #include <grp.h>
  39. #include <unistd.h>
  40. #include <stdlib.h>
  41. const char* HylaFAXServer::version = HYLAFAX_VERSION;
  42. int HylaFAXServer::_debugSleep = 0;
  43. fxStrArray HylaFAXServer::configOptions;
  44. /*
  45.  * NB: The remainder of the instance state is
  46.  * initialized in initServer which is expected to
  47.  * be called before any other operation is done
  48.  * (through open).  This is required because some
  49.  * initialization work is done by virtual methods
  50.  * that cannot be invoked from the constructor.
  51.  */
  52. HylaFAXServer::HylaFAXServer()
  53.     : defJob("")
  54. {
  55.     state = 0;
  56.     xferfaxlog = -1;
  57.     loginAttempts = 0; // NB: not reset by REIN command
  58.     adminAttempts = 0; // NB: not reset by REIN command
  59.     idcache = NULL;
  60. #ifdef HAVE_PAM
  61. pam_chrooted = false;
  62. #endif
  63.     data = -1; // current data connection (socket)
  64.     pdata = -1; // passive mode data connect (socket)
  65.     faxqFd = -1;
  66.     clientFd = -1;
  67.     char buff[64];
  68.     (void) gethostname(buff, sizeof(buff));
  69.     hostname = buff;
  70.     hostaddr = "unknown"; // derived classes should fill-in
  71.     lastModTime = 0; // shutdown file mod time
  72.     discTime = 0; // shutdown forced disconnect time
  73.     denyTime = 0; // shutdown service denial time
  74.     /*
  75.      * Calculate the time differential between
  76.      * the local timezone and GMT for adjusting
  77.      * client-specified time values that are given
  78.      * in GMT.
  79.      *
  80.      * mktime() gives us the seconds elapsed since the
  81.      * beginning of calendar time.  And so in a
  82.      * "daylight savings" condition the clock shows 
  83.      * a time ahead of calendar time - where that 
  84.      * amount of time has not elapsed yet - and thus
  85.      * subtracting mktime(&tm) from mktime(&gmt) will 
  86.      * not immediately give us the clock offset 
  87.      * between local time and GMT when DST applies.  To
  88.      * compensate we set tm.tm_isdst to 0 always, and 
  89.      * this will force mktime() to believe that the
  90.      * those seconds have elapsed, and thus we'll get
  91.      * an accurate gmtoff value.
  92.      */
  93.     time_t now = Sys::now();
  94.     struct tm gmt = *gmtime(&now);
  95.     struct tm tm = *localtime(&now);
  96.     tm.tm_isdst = 0;
  97.     gmtoff = mktime(&gmt) - mktime(&tm);
  98. #if HAS_TM_ZONE
  99.     /*
  100.      * BSD/OS doesn't support the global timezone
  101.      * information so setup substitutes here.
  102.      */
  103.     tzname[0] = tm.tm_zone;
  104.     tzname[1] = NULL;
  105. #endif
  106.     /*
  107.      * Some versions of  glibc (like RHEL4) will revert to UTC in
  108.      * the chroot if it can't find the zoneinfo file and no TZ is
  109.      * set in the environment.
  110.      * We'll set the TZ to our crafted TZ to make sure that we
  111.      * have the right offset even if no timezone DST info is
  112.      * avaliable in the chroot.
  113.      */
  114.     fxStr tz = fxStr::format("CUT%d:%02d", (gmtoff / 3600), ((gmtoff / 60) % 60));
  115.     setenv("TZ", tz, 0);
  116.     cachedTIFF = NULL;
  117. }
  118. HylaFAXServer::~HylaFAXServer()
  119. {
  120.     dologout(0);
  121. }
  122. /*
  123.  * Initialize the state of the server.  Note that this
  124.  * is used to implement the REIN command and for that
  125.  * it doesn't work entirely because state set from the
  126.  * configuration files is not accessible after a login
  127.  * because the sever does a chroot to the top of the
  128.  * spooling area.  The only way to make this work is
  129.  * to keep all the configuration files in the spooling
  130.  * area which is not folks want when things are shared
  131.  * through NFS (i.e. server binaries and config files
  132.  * are NFS-mounted by the spooling area is private).
  133.  */
  134. void
  135. HylaFAXServer::initServer(void)
  136. {
  137.     if (_debugSleep) // Allow a debuger time to attach
  138.     {
  139. logDebug("Sleeping %d for debugger", _debugSleep);
  140. sleep(_debugSleep);
  141.     }
  142.     end_login(); // reset user-related state
  143.     /*
  144.      * Default state:
  145.      *   o send long replies
  146.      *   o use GMT for time values
  147.      *   o auto-detect whether filesystem has BSD or SysV
  148.      *     semantics for setting the GID on created files
  149.      */
  150.     state = S_LREPLIES|S_USEGMT|S_CHECKGID;
  151.     restart_point = 0; // data-transfer-related state
  152.     mode = MODE_S;
  153.     form = FORM_PS;
  154.     type = TYPE_A;
  155.     stru = STRU_F;
  156.     initDefaultJob(); // reset default job state
  157.     curJob = &defJob;
  158.     if (data != -1) // data transfer-related state
  159. Sys::close(data), data = -1;
  160.     if (pdata != -1)
  161. Sys::close(pdata), pdata = -1;
  162.     if (trigSpec != "") {
  163. fxStr emsg;
  164. cancelTrigger(emsg);
  165.     }
  166.     // XXX FIFO state
  167.     pushedToken = T_NIL;
  168.     recvCC = 0; // no data present in buffer
  169.     recvNext = 0;
  170.     consecutiveBadCmds = 0;
  171.     resetConfig();
  172.     readConfig(FAX_SYSCONF);
  173.     readConfig(FAX_LIBDATA "/hfaxd.conf");
  174.     for (u_int i = 0; i < configOptions.length(); i++)
  175. readConfigItem(configOptions[i]);
  176. }
  177. static void
  178. tiffErrorHandler(const char* module, const char* fmt0, va_list ap)
  179. {
  180.     fxStr fmt = (module != 0) ?
  181.         fxStr::format("%s: Warning, %s.", module, fmt0)
  182.         : fxStr::format("Warning, %s.", fmt0);
  183.     vlogError(fmt, ap);
  184. }
  185. static void
  186. tiffWarningHandler(const char* module, const char* fmt0, va_list ap)
  187. {
  188.     fxStr fmt = (module != 0) ?
  189.         fxStr::format("%s: Warning, %s.", module, fmt0)
  190.         : fxStr::format("Warning, %s.", fmt0);
  191.     vlogWarning(fmt, ap);
  192. }
  193. void
  194. HylaFAXServer::open(void)
  195. {
  196.     initServer(); // complete state initialization
  197.     fxStr emsg;
  198.     if (!initClientFIFO(emsg)) {
  199.         logInfo("connection refused (%s) from %s [%s]",
  200.     (const char*) emsg,
  201.     (const char*) remotehost, (const char*) remoteaddr);
  202. reply(420, "%s server cannot initialize: %s",
  203.     (const char*) hostname, (const char*) emsg);
  204. dologout(-1);
  205.     }
  206.     ctrlFlags = fcntl(STDIN_FILENO, F_GETFL); // for parser
  207.     if (isShutdown(true))
  208. reply(220, "%s HylaFAX server shut down; available only for admin use.",
  209.     (const char*) hostname);
  210.     else
  211. reply(220, "%s server (%s) ready.", (const char*) hostname, version);
  212.     if (TRACE(TIFF)) {
  213. TIFFSetErrorHandler(tiffErrorHandler);
  214. TIFFSetWarningHandler(tiffWarningHandler);
  215.     } else {
  216. TIFFSetErrorHandler(NULL);
  217. TIFFSetWarningHandler(NULL);
  218.     }
  219. }
  220. void
  221. HylaFAXServer::close()
  222. {
  223.     dologout(-1);
  224. }
  225. void
  226. HylaFAXServer::setupPermissions(void)
  227. {
  228.     uid_t euid = geteuid();
  229.     struct passwd* pwd = getpwnam(FAX_USER);
  230.     if (!pwd)
  231. logError("No fax user "%s" defined on your system!n"
  232.     "This software is not installed properly!", FAX_USER);
  233.     else if (euid == 0) {
  234. if (initgroups(pwd->pw_name, pwd->pw_gid) != 0)
  235.     logError("Can not setup permissions (supplementary groups): %m");
  236. if (setegid(pwd->pw_gid) < 0)
  237.     logError("Can not setup permissions (gid): %m");
  238. else if (seteuid(pwd->pw_uid) < 0)
  239.     logError("Can not setup permissions (uid): %m");
  240. else {
  241.     faxuid = pwd->pw_gid;
  242.     endpwent();
  243.     return;
  244. }
  245.     } else {
  246. faxuid = pwd->pw_gid;
  247. uid_t faxuid = pwd->pw_uid;
  248. setpwent();
  249. pwd = getpwuid(euid);
  250. if (!pwd)
  251.     logError("Can not figure out the identity of uid %u", euid);
  252. else if (pwd->pw_uid != faxuid)
  253.     logError("Configuration error; "
  254. "the fax server must run as the fax user "%s".", FAX_USER);
  255. else {
  256.     endpwent();
  257.     return;
  258. }
  259.     }
  260.     exit(-1);
  261. }
  262. /*
  263.  * Close all open descriptors and unlink any
  264.  * Dispatcher i/o handlers.
  265.  */
  266. void
  267. HylaFAXServer::closeAllBut(int fd)
  268. {
  269.     Dispatcher& disp = Dispatcher::instance();
  270.     for (int f = Sys::getOpenMax()-1; f >= 0; f--)
  271. if (f != fd) {
  272.     IOHandler* h = disp.handler(f, Dispatcher::ReadMask);
  273.     if (h)
  274. disp.unlink(f);
  275.     Sys::close(f);
  276. }
  277. }
  278. /*
  279.  * Unlink all dispatcher i/o handlers and close
  280.  * their file descriptor.
  281.  */
  282. void
  283. HylaFAXServer::closeAllDispatched()
  284. {
  285.     Dispatcher& disp = Dispatcher::instance();
  286.     for (int f = Sys::getOpenMax()-1; f >= 0; f--)
  287.     {
  288. IOHandler* h = disp.handler(f, Dispatcher::ReadMask);
  289. if (h)
  290. {
  291.     disp.unlink(f);
  292.     Sys::close(f);
  293. }
  294.     }
  295. }
  296. const char*
  297. HylaFAXServer::fixPathname(const char* file)
  298. {
  299.     return (!IS(LOGGEDIN) && file[0] == '/' ? file+1 : file);
  300. }
  301. bool
  302. HylaFAXServer::readShutdownFile(void)
  303. {
  304.     bool ok = false;
  305.     FILE* fd = fopen(fixPathname(shutdownFile), "r");
  306.     if (fd != NULL) {
  307. struct tm tm;
  308. int deny, disc;
  309. memset(&tm, 0, sizeof (tm));
  310. int n = fscanf(fd, "%d %d %d %d %d %d %dn",
  311.     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
  312.     &deny, &disc);
  313. if (n == 7) {
  314.     tm.tm_year -= 1900;
  315.     tm.tm_isdst = -1;
  316.     time_t shut = mktime(&tm);
  317.     if (shut != (time_t) -1) {
  318. denyTime = shut - 3600 * (deny / 100) + 60 * (deny % 100);
  319. discTime = shut - 3600 * (disc / 100) + 60 * (disc % 100);
  320. shutdownMsg = "";
  321. char buf[1024];
  322. while (fgets(buf, sizeof (buf), fd))
  323.     shutdownMsg.append(buf);
  324. ok = true;
  325.     } else
  326. logError("%s: Invalid shutdown time, mktime conversion failed;"
  327.     "Year=%d Mon=%d Day=%d Hour=%d Min=%d"
  328.     , (const char*) shutdownFile
  329.     , tm.tm_year+1900
  330.     , tm.tm_mon
  331.     , tm.tm_mday
  332.     , tm.tm_hour
  333.     , tm.tm_min
  334. );
  335. } else
  336.     logError("%s: shutdown file format error",
  337. (const char*) shutdownFile);
  338. (void) fclose(fd);
  339.     } else
  340. logError("%s: Cannot open shutdown file: %s",
  341.     (const char*) shutdownFile, strerror(errno));
  342.     return (ok);
  343. }
  344. bool
  345. HylaFAXServer::isShutdown(bool quiet)
  346. {
  347.     struct stat sb;
  348.     if (shutdownFile == "" || Sys::stat(fixPathname(shutdownFile), sb) < 0)
  349. return (false);
  350.     if (sb.st_mtime != lastModTime) {
  351. if (!readShutdownFile())
  352.     return (false);
  353. lastModTime = sb.st_mtime;
  354.     }
  355.     time_t now = Sys::now();
  356.     if (!quiet) { // possibly send client shutdown msg
  357. time_t timeToDisconnect = discTime - now;
  358. time_t lastMsg = now-lastTime;
  359. bool sendShutDownMsg =
  360.        (lastTime == 0) // first time
  361.     || (timeToDisconnect < 60) // <60 seconds, warn continuously
  362. // <15 minutes, warn ever 5 minutes
  363.     || (timeToDisconnect < 15*60 && lastMsg > 5*60)
  364. // <24 hours, warn every 30 minutes
  365.          || (timeToDisconnect < 24*60*60 && lastMsg > 30*60)
  366. // >24 hours, warn ever day
  367.          || (timeToDisconnect < 24*60*60 && lastMsg >= 24*60*60)
  368.     ;
  369. if (sendShutDownMsg) {
  370.     autospout = shutdownMsg; // XXX append?
  371.     lastTime = now;
  372. }
  373.     }
  374.     return (now > discTime);
  375. }
  376. void
  377. HylaFAXServer::statusCmd(void)
  378. {
  379.     lreply(211, "%s HylaFAX server status:", (const char*) hostname);
  380.     printf("    %srn", version);
  381.     printf("    Connected to %s", (const char*) remotehost);
  382.     if (!isdigit(remotehost[0]))
  383. printf(" (%s)", (const char*) remoteaddr);
  384.     printf("rn");
  385.     if (IS(LOGGEDIN)) {
  386. printf("    Logged in as user %s (uid %u)%srn"
  387.     , (const char*) the_user
  388.     , uid
  389.     , IS(PRIVILEGED) ? " (with administrative privileges)" : ""
  390. );
  391. u_int len = strlen(cwd->pathname)-1; // strip trailing "/"
  392. printf("    "%.*s" is the current directoryrn",
  393.     len ? len : len+1, cwd->pathname);
  394. printf("    Current job: ");
  395. if (curJob->jobid == "default")
  396.     printf("(default)rn");
  397. else
  398.     printf("jobid %s groupid %srn",
  399. (const char*) curJob->jobid, (const char*) curJob->groupid);
  400.     } else if (IS(WAITPASS))
  401. printf("    Waiting for passwordrn");
  402.     else
  403. printf("    Waiting for user namern");
  404.     printf("    Time values are handled in %srn",
  405. IS(USEGMT) ? "GMT" : tzname[0]);
  406.     printf("    Idle timeout set to %d secondsrn", idleTimeout);
  407.     printf("    %s long repliesrn", IS(LREPLIES) ? "Using" : "Not using");
  408.     if (discTime > 0)
  409. printf("    Server scheduled to be unavailable at %.24srn",
  410.     asctime(cvtTime(discTime)));
  411.     else
  412. printf("    No server down time currently scheduledrn");
  413.     printf("    HylaFAX scheduler reached at %s (%sconnected)rn"
  414. , (const char*) faxqFIFOName
  415. , faxqFd == -1 ? "not " : ""
  416.     );
  417.     if (clientFd != -1)
  418. printf("    Server FIFO is /%s (%sopen)rn"
  419.     , (const char*) clientFIFOName
  420.     , clientFd == -1 ? "not " : ""
  421. );
  422.     if (IS(WAITFIFO))
  423. printf("    Waiting for response from HylaFAX schedulerrn");
  424.     FileCache::printStats(stdout);
  425.     printTransferStatus(stdout);
  426.     netStatus(stdout); // transport-dependent status
  427.     reply(211, "End of status");
  428. }
  429. int
  430. HylaFAXServer::inputReady(int fd)
  431. {
  432.     if (fd == STDIN_FILENO)
  433. return parse();
  434.     else if (fd == clientFd)
  435. return FIFOInput(fd);
  436.     fatal("Input ready on unknown file descriptor %d", fd);
  437.     return (0); // to shutup compilers
  438. }
  439. void
  440. HylaFAXServer::fatal(const char* fmt, ...)
  441. {
  442.     va_list ap;
  443.     va_start(ap, fmt);
  444.     vreply(451, fxStr::format("Error in server: %s", fmt), ap);
  445.     va_end(ap);
  446.     reply(221, "Closing connection due to server error.");
  447.     dologout(0);
  448.     /*NOTREACHED*/
  449. }
  450. void
  451. HylaFAXServer::reply(int code, const char* fmt, ...)
  452. {
  453.     va_list ap;
  454.     va_start(ap, fmt);
  455.     vreply(code, fmt, ap);
  456.     va_end(ap);
  457. }
  458. void
  459. HylaFAXServer::vreply(int code, const char* fmt, va_list ap)
  460. {
  461.     if (autospout != "") {
  462.         printf("%d-", code);
  463.         int i = 0;
  464.         while (autospout[i] != '') {
  465.             if (autospout[i] == 'n') {
  466.                 fputs("rn", stdout);
  467.                 if (autospout[++i])
  468.                     printf("%d-", code);
  469.             } else
  470.                 putchar(autospout[i++]);
  471.         }
  472.         if (autospout[--i] != 'n')
  473.             printf("rn");
  474.         autospout = "";
  475.     }
  476.     fxStackBuffer buf;
  477.     buf.vput(fmt, ap);
  478.     fprintf(stdout, "%d %.*srn", code, buf.getLength(), (const char*) buf);
  479.     fflush(stdout);
  480.     if (TRACE(PROTOCOL))
  481.         logDebug("<--- %d %.*s", code, buf.getLength(), (const char*) buf);
  482. }
  483. void
  484. HylaFAXServer::lreply(int code, const char* fmt, ...)
  485. {
  486.     va_list ap;
  487.     va_start(ap, fmt);
  488.     vlreply(code, fmt, ap);
  489.     va_end(ap);
  490. }
  491. void
  492. HylaFAXServer::vlreply(int code, const char* fmt, va_list ap)
  493. {
  494.     if (IS(LREPLIES)) {
  495. fxStackBuffer buf;
  496. buf.vput(fmt, ap);
  497. printf("%d-%.*srn", code, buf.getLength(), (const char*) buf);
  498. fflush(stdout);
  499. if (TRACE(PROTOCOL))
  500.     logDebug("<--- %d-%.*s", code, buf.getLength(), (const char*) buf);
  501.     }
  502. }
  503. /* Format and send reply containing system error number. */
  504. void
  505. HylaFAXServer::perror_reply(int code, const char* string, int errnum)
  506. {
  507.     reply(code, "%s: %s.", string, strerror(errnum));
  508. }
  509. void
  510. HylaFAXServer::ack(int code, const char* s)
  511. {
  512.     reply(code, "%s command successful.", s);
  513. }
  514. struct tm*
  515. HylaFAXServer::cvtTime(const time_t& t) const
  516. {
  517.     return IS(USEGMT) ? gmtime(&t) : localtime(&t);
  518. }
  519. u_int HylaFAXServer::getJobNumber(fxStr& emsg)
  520.     { return (Sequence::getNext(FAX_SENDDIR "/" FAX_SEQF, emsg)); }
  521. u_int HylaFAXServer::getDocumentNumber(fxStr& emsg)
  522.     { return (Sequence::getNext(FAX_DOCDIR "/" FAX_SEQF, emsg)); }
  523. void
  524. HylaFAXServer::sanitize(fxStr& s)
  525. {
  526.     for (u_int i = 0; i < s.length(); i++)
  527. if (!isascii(s[i]) || !isprint(s[i]))
  528.     s[i] = '?';
  529. }
  530. /*
  531.  * Convert modem name from canonical format back
  532.  * to a pathname by replacing '_'s with '/'s.
  533.  */
  534. void
  535. HylaFAXServer::canonModem(fxStr& s)
  536. {
  537.     u_int l = 0;
  538.     while ((l = s.next(l, '_')) < s.length())
  539. s[l] = '/';
  540. }
  541. /*
  542.  * Convert pathname to a device ID by
  543.  * replacing '/'s with '_'s.
  544.  */
  545. void
  546. HylaFAXServer::canonDevID(fxStr& s)
  547. {
  548.     u_int l = 0;
  549.     while ((l = s.next(l, '/')) < s.length())
  550. s[l] = '_';
  551. }
  552. /*
  553.  * Configuration support.
  554.  */
  555. void
  556. HylaFAXServer::resetConfig()
  557. {
  558.     FaxConfig::resetConfig();
  559.     setupConfig();
  560. }
  561. #define N(a) (sizeof (a) / sizeof (a[0]))
  562. /*
  563.  * logFacility *must* be the first entry - see its handling
  564.  * below in setConfigItem()
  565.  */
  566. HylaFAXServer::stringtag HylaFAXServer::strings[] = {
  567. { "logfacility", &HylaFAXServer::logFacility, LOG_FAX },
  568. { "faxcontact", &HylaFAXServer::faxContact, "FaxMaster" },
  569. { "useraccessfile", &HylaFAXServer::userAccessFile, "/" FAX_PERMFILE },
  570. { "shutdownfile", &HylaFAXServer::shutdownFile, "/etc/shutdown" },
  571. { "xferlogfile", &HylaFAXServer::xferfaxLogFile, "/etc/clientlog" },
  572. { "jobfmt", &HylaFAXServer::jobFormat,
  573.   "%-4j %3i %1a %6.6o %-12.12e %5P %5D %7z %.25s" },
  574. { "rcvfmt", &HylaFAXServer::recvFormat,
  575.   "%-7m %4p%1z %-8.8o %14.14s %7t %f" },
  576. { "modemfmt", &HylaFAXServer::modemFormat, "Modem %m (%n): %s" },
  577. { "filefmt", &HylaFAXServer::fileFormat,
  578.   "%-7p %3l %8o %8s %-12.12m %.48f" },
  579. { "faxqfifoname", &HylaFAXServer::faxqFIFOName, "/" FAX_FIFO },
  580. { "systemtype", &HylaFAXServer::systemType,
  581.   "UNIX Type: L8 Version: SVR4" },
  582. { "admingroup", &HylaFAXServer::admingroup },
  583. #ifdef HAVE_LDAP
  584. { "ldapserveruri", &HylaFAXServer::ldapServerUri, "" },
  585. { "ldapbasedn", &HylaFAXServer::ldapBaseDN, "" },
  586. { "ldapreqgroup", &HylaFAXServer::ldapReqGroup, "" },
  587. #endif
  588. };
  589. /*
  590.  * jobprotection needs to be first as well, see setConfigItem() below
  591.  */
  592. HylaFAXServer::numbertag HylaFAXServer::numbers[] = {
  593. { "jobprotection", &HylaFAXServer::jobProtection, 0644 },
  594. { "recvqprotection", &HylaFAXServer::recvqProtection, 0644 },
  595. { "servertracing", &HylaFAXServer::tracingLevel, TRACE_SERVER },
  596. { "idletimeout", &HylaFAXServer::idleTimeout, 900 },
  597. { "maxidletimeout", &HylaFAXServer::maxIdleTimeout, 7200 },
  598. { "locktimeout", &HylaFAXServer::lockTimeout, 0 },
  599. { "maxlocktimeout", &HylaFAXServer::maxLockTimeout, 60 },
  600. { "maxloginattempts", &HylaFAXServer::maxLoginAttempts, 5 },
  601. { "maxadminattempts", &HylaFAXServer::maxAdminAttempts, 5 },
  602. { "maxconsecutivebadcmds",&HylaFAXServer::maxConsecutiveBadCmds,10 },
  603. #ifdef HAVE_LDAP
  604. { "ldapversion", &HylaFAXServer::ldapVersion, 3 },
  605. #endif
  606. };
  607. void
  608. HylaFAXServer::setupConfig()
  609. {
  610.     int i;
  611.     for (i = N(strings)-1; i >= 0; i--)
  612. (*this).*strings[i].p = (strings[i].def ? strings[i].def : "");
  613.     for (i = N(numbers)-1; i >= 0; i--)
  614. (*this).*numbers[i].p = numbers[i].def;
  615.     faxContact.append("@" | hostname);
  616. admingroup = "faxadmin";
  617. }
  618. void
  619. HylaFAXServer::configError(const char* fmt, ...)
  620. {
  621.     va_list ap;
  622.     va_start(ap, fmt);
  623.     vlogError(fmt, ap);
  624.     va_end(ap);
  625. }
  626. void
  627. HylaFAXServer::configTrace(const char* fmt, ...)
  628. {
  629.     if (TRACE(CONFIG)) {
  630. va_list ap;
  631. va_start(ap, fmt);
  632. vlogError(fmt, ap);
  633. va_end(ap);
  634.     }
  635. }
  636. bool
  637. HylaFAXServer::setConfigItem(const char* tag, const char* value)
  638. {
  639.     u_int ix;
  640.     if (findTag(tag, (const tags*) strings, N(strings), ix)) {
  641. (*this).*strings[ix].p = value;
  642. switch (ix) {
  643. case 0: setLogFacility(logFacility); break;
  644. }
  645.     } else if (findTag(tag, (const tags*) numbers, N(numbers), ix)) {
  646. (*this).*numbers[ix].p = getNumber(value);
  647. switch (ix) {
  648. case 0: if ( (jobProtection & 0600) != 0600)
  649.     {
  650. logError("JobProtection value must include 0600, forcing");
  651. jobProtection |= 0600;
  652.     }
  653. }
  654.     } else
  655. return (false);
  656.     return (true);
  657. }
  658. #undef N