?? hylafaxserver.c++
字號:
/* $Id: HylaFAXServer.c++,v 1.21 2006/06/12 18:28:54 aidan Exp $ *//* * Copyright (c) 1995-1996 Sam Leffler * Copyright (c) 1995-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 "port.h"#include "Sys.h"#include "config.h"#include "tiffio.h"#include "HylaFAXServer.h"#include "Dispatcher.h"#include "StackBuffer.h"#include "Sequence.h"#include <ctype.h>#include <sys/file.h>#include <pwd.h>#include <limits.h>#include <grp.h>#include <unistd.h>#include <stdlib.h>const char* HylaFAXServer::version = HYLAFAX_VERSION;/* * NB: The remainder of the instance state is * initialized in initServer which is expected to * be called before any other operation is done * (through open). This is required because some * initialization work is done by virtual methods * that cannot be invoked from the constructor. */HylaFAXServer::HylaFAXServer() : defJob(""){ state = 0; xferfaxlog = -1; loginAttempts = 0; // NB: not reset by REIN command adminAttempts = 0; // NB: not reset by REIN command idcache = NULL;#ifdef HAVE_PAM pamh = NULL; pam_chrooted = false;#endif data = -1; // current data connection (socket) pdata = -1; // passive mode data connect (socket) faxqFd = -1; clientFd = -1; char buff[64]; (void) gethostname(buff, sizeof(buff)); hostname = buff; hostaddr = "unknown"; // derived classes should fill-in lastModTime = 0; // shutdown file mod time discTime = 0; // shutdown forced disconnect time denyTime = 0; // shutdown service denial time /* * Calculate the time differential between the local timezone * and GMT for adjusting client-specified time values that are * given in GMT. * * We want the actual offset of the local now from UTC, * This means we have to "force" daylight savings off, otherwise * the offset we get back is of the real timezone (the time * functions automatically compensate if DST is set). * * Because we take the actual offset instead of a real timezone, * we force the TZ a format CUT<offset> instead of an actual * timezone like EST<offset>EDT, or PST<offset>PDT. This means * we no longer have to rely on the system being able to do the * DST offset. */ time_t now = Sys::now(); struct tm gmt = *gmtime(&now); struct tm tm = *localtime(&now); tm.tm_isdst = 0; gmtoff = mktime(&gmt) - mktime(&tm);#if HAS_TM_ZONE /* * BSD/OS doesn't support the global timezone * information so setup substitutes here. */ tzname[0] = tm.tm_zone; tzname[1] = NULL;#endif /* * Some versions of glibc (like RHEL4) will revert to UTC in * the chroot if it can't find the zoneinfo file and no TZ is * set in the environment. * We'll set the TZ to our crafted TZ to make sure that we * have the right offset even if no timezone DST info is * available in the chroot. */ fxStr tz = fxStr::format("CUT%d:%02d", (gmtoff / 3600), ((gmtoff / 60) % 60)); setenv("TZ", tz, 0); cachedTIFF = NULL;}HylaFAXServer::~HylaFAXServer(){ dologout(0);}/* * Initialize the state of the server. Note that this * is used to implement the REIN command and for that * it doesn't work entirely because state set from the * configuration files is not accessible after a login * because the sever does a chroot to the top of the * spooling area. The only way to make this work is * to keep all the configuration files in the spooling * area which is not folks want when things are shared * through NFS (i.e. server binaries and config files * are NFS-mounted by the spooling area is private). */voidHylaFAXServer::initServer(void){ end_login(); // reset user-related state /* * Default state: * o send long replies * o use GMT for time values * o auto-detect whether filesystem has BSD or SysV * semantics for setting the GID on created files */ state = S_LREPLIES|S_USEGMT|S_CHECKGID; restart_point = 0; // data-transfer-related state mode = MODE_S; form = FORM_PS; type = TYPE_A; stru = STRU_F; initDefaultJob(); // reset default job state curJob = &defJob; if (data != -1) // data transfer-related state Sys::close(data), data = -1; if (pdata != -1) Sys::close(pdata), pdata = -1; if (trigSpec != "") { fxStr emsg; cancelTrigger(emsg); } // XXX FIFO state pushedToken = T_NIL; recvCC = 0; // no data present in buffer recvNext = 0; consecutiveBadCmds = 0; resetConfig(); readConfig(FAX_SYSCONF); readConfig(FAX_LIBDATA "/hfaxd.conf");}static voidtiffErrorHandler(const char* module, const char* fmt0, va_list ap){ fxStr fmt = (module != 0) ? fxStr::format("%s: Warning, %s.", module, fmt0) : fxStr::format("Warning, %s.", fmt0); vlogError(fmt, ap);}static voidtiffWarningHandler(const char* module, const char* fmt0, va_list ap){ fxStr fmt = (module != 0) ? fxStr::format("%s: Warning, %s.", module, fmt0) : fxStr::format("Warning, %s.", fmt0); vlogWarning(fmt, ap);}voidHylaFAXServer::open(void){ initServer(); // complete state initialization fxStr emsg; if (!initClientFIFO(emsg)) { logInfo("connection refused (%s) from %s [%s]", (const char*) emsg, (const char*) remotehost, (const char*) remoteaddr); reply(420, "%s server cannot initialize: %s", (const char*) hostname, (const char*) emsg); dologout(-1); } ctrlFlags = fcntl(STDIN_FILENO, F_GETFL); // for parser if (isShutdown(true)) reply(220, "%s HylaFAX server shut down; available only for admin use.", (const char*) hostname); else reply(220, "%s server (%s) ready.", (const char*) hostname, version); if (TRACE(TIFF)) { TIFFSetErrorHandler(tiffErrorHandler); TIFFSetWarningHandler(tiffWarningHandler); } else { TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); }}voidHylaFAXServer::close(){ dologout(-1);}voidHylaFAXServer::setupPermissions(void){ uid_t euid = geteuid(); struct passwd* pwd = getpwnam(FAX_USER); if (!pwd) logError("No fax user \"%s\" defined on your system!\n" "This software is not installed properly!", FAX_USER); else if (euid == 0) { if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) logError("Can not setup permissions (supplementary groups): %m"); if (setegid(pwd->pw_gid) < 0) logError("Can not setup permissions (gid): %m"); else if (seteuid(pwd->pw_uid) < 0) logError("Can not setup permissions (uid): %m"); else { faxuid = pwd->pw_gid; endpwent(); return; } } else { faxuid = pwd->pw_gid; uid_t faxuid = pwd->pw_uid; setpwent(); pwd = getpwuid(euid); if (!pwd) logError("Can not figure out the identity of uid %u", euid); else if (pwd->pw_uid != faxuid) logError("Configuration error; " "the fax server must run as the fax user \"%s\".", FAX_USER); else { endpwent(); return; } } exit(-1);}/* * Close all open descriptors and unlink any * Dispatcher i/o handlers. */voidHylaFAXServer::closeAllBut(int fd){ Dispatcher& disp = Dispatcher::instance(); for (int f = Sys::getOpenMax()-1; f >= 0; f--) if (f != fd) { IOHandler* h = disp.handler(f, Dispatcher::ReadMask); if (h) disp.unlink(f); Sys::close(f); }}/* * Unlink all dispatcher i/o handlers and close * their file descriptor. */voidHylaFAXServer::closeAllDispatched(){ Dispatcher& disp = Dispatcher::instance(); for (int f = Sys::getOpenMax()-1; f >= 0; f--) { IOHandler* h = disp.handler(f, Dispatcher::ReadMask); if (h) { disp.unlink(f); Sys::close(f); } }}const char*HylaFAXServer::fixPathname(const char* file){ return (!IS(LOGGEDIN) && file[0] == '/' ? file+1 : file);}boolHylaFAXServer::readShutdownFile(void){ bool ok = false; FILE* fd = fopen(fixPathname(shutdownFile), "r"); if (fd != NULL) { struct tm tm; int deny, disc; memset(&tm, 0, sizeof (tm)); int n = fscanf(fd, "%d %d %d %d %d %d %d\n", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &deny, &disc); if (n == 7) { tm.tm_year -= 1900; tm.tm_isdst = -1; time_t shut = mktime(&tm); if (shut != (time_t) -1) { denyTime = shut - 3600 * (deny / 100) + 60 * (deny % 100); discTime = shut - 3600 * (disc / 100) + 60 * (disc % 100);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -