📄 main.c++
字号:
/* $Id: main.c++,v 1.7 2006/08/12 20:51:30 pfournier 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 "InetFaxServer.h"#if CONFIG_UNIXTRANSPORT#include "UnixFaxServer.h"#endif#ifdef OLDPROTO_SUPPORT#include "OldProtocol.h"#endif#ifdef SNPP_SUPPORT#include "SNPPServer.h"#endif#ifdef HTTP_SUPPORT#include "HTTPServer.h"#endif#include "Dispatcher.h"#include "Array.h"#include "Sys.h"#include "Socket.h"#include "config.h"static jmp_buf problem;static voidsigCleanup(int sig){ logError("CAUGHT SIGNAL %d", sig); longjmp(problem, 1);}static voidfatal(const char* fmt ...){ va_list ap; va_start(ap, fmt); vlogError(fmt, ap); va_end(ap); exit(-1);}#define PATH_DEVNULL "dev/null"#define PATH_DEVTCP "dev/tcp"#define PATH_NETCONFIG "etc/netconfig"#define PATH_DEVSOCKSYS "dev/socksys"/* * Verify and possibly setup the chroot'd filesystem as * required by the system. Specifically, create a private * copy of /dev/null and any networking-related files * required by SVR4-based TCP/IP support. We do this work * because the process runs chroot'd to the top of the * spooling area so normal files in the root filesystem * are inaccessible. * * NB: This work could be done once in a setup script but * creating duplicates of character special device files * is not simple from the shell. */static voidCheckSpoolingSetup(void){ struct stat sb; uid_t ouid = geteuid(); (void) seteuid(0); mode_t omask = umask(0); /* * Craft a private /dev/null in the chroot'd filesystem * for use by syslog because some syslogs require this * to function correctly. */ if (!Sys::isCharSpecialFile(PATH_DEVNULL)) { if (!Sys::isCharSpecialFile("/" PATH_DEVNULL, sb)) fatal("stat(%s): %s", "/" PATH_DEVNULL, strerror(errno)); if (mknod(PATH_DEVNULL, sb.st_mode, sb.st_rdev) < 0) fatal("Could not create %s: %s", PATH_DEVNULL, strerror(errno)); } /* * If the system appears to support SVR4-style TCP/IP * support then craft a private copy of the necessary * files so that socket-related calls can be made after * chroot'ing to the top of the spooling area. * * NB: It is assumed that the dev subdirectory is already * present (make install or similar should create it). */ if (Sys::isCharSpecialFile("/" PATH_DEVTCP, sb) && !Sys::isCharSpecialFile(PATH_DEVTCP)) { if (mknod(PATH_DEVTCP, sb.st_mode, sb.st_rdev) < 0) fatal("Could not create %s: %s", PATH_DEVTCP, strerror(errno)); /* * Copy /etc/netconfig if not already present. */ if (Sys::stat(PATH_NETCONFIG, sb) < 0) { int src = Sys::open("/" PATH_NETCONFIG, O_RDONLY); if (src >= 0) { int dst = Sys::open(PATH_NETCONFIG, O_WRONLY|O_CREAT, 0444); if (dst < 0) fatal("creat(%s): %s", PATH_NETCONFIG, strerror(errno)); char buf[4096]; int cc; while ((cc = read(src, buf, sizeof (buf))) > 0) if (write(dst, buf, cc) < 0) fatal("write(%s): %s", PATH_NETCONFIG, strerror(errno)); close(dst); close(src); } else logWarning("%s: Cannot open: %s", "/" PATH_NETCONFIG, strerror(errno)); } } /* * SCO OS 5 apparently needs a /dev/socksys to implement * setsockopt calls (sigh); create one in the chroot'd * area if one exists in the root filesystem. */ if (Sys::isCharSpecialFile("/" PATH_DEVSOCKSYS, sb) && !Sys::isCharSpecialFile(PATH_DEVSOCKSYS)) if (mknod(PATH_DEVSOCKSYS, sb.st_mode, sb.st_rdev) < 0) fatal("Could not create %s: %s", PATH_DEVSOCKSYS, strerror(errno)); (void) umask(omask); seteuid(ouid);}/* * Break the association with the controlling tty. * Note that we do not close all the open file descriptors * because many systems cache open descriptors within libraries * for performance reasons and do not react well when you close * them w/o telling them about it (and some don't react well * even when you *DO* tell them). Since we know we're called * very early on from main in all our apps we just assume that * we only need to remove the stdin+stdout+stderr before forking * and starting a new session. */static voiddetachFromTTY(void){ int fd = Sys::open(_PATH_DEVNULL, O_RDWR); if (fd == -1) fatal("Could not open null device file %s.", _PATH_DEVNULL); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); Sys::close(fd); switch (fork()) { case 0: break; // child, continue case -1: _exit(1); // error default: _exit(0); // parent, terminate } (void) setsid();}static voidusage(const char* appName){ fatal("usage: %s [-d] [-o port] [-O] [-h port] [-H] [-l bindaddress] [-i port] [-I] [-s port] [-S] [-u socket] [-q queue-directory]", appName);}fxDECLARE_PtrArray(IOHandlerArray, IOHandler*)fxIMPLEMENT_PtrArray(IOHandlerArray, IOHandler*)static IOHandlerArray handlers;static voidnewInetServer(void){ InetFaxServer* server = new InetFaxServer; server->open(); handlers.append(server);}intmain(int argc, char** argv, char** envp){ const char *bindaddress = NULL; HylaFAXServer::setLogFacility(LOG_FAX); HylaFAXServer::setupLogging("HylaFAX"); HylaFAXServer::setupPermissions(); fxStr appName = argv[0]; u_int l = appName.length(); appName = appName.tokenR(l, '/'); optind = 1; opterr = 0; int c; const char* opts = "dHh:Ii:Oo:q:Ss:u:l:"; /* * Deduce the spooling directory and whether or not to * detach the process from the controlling tty. The * latter is complicated by the fact that we run both * as a master-server process and as a subprocess to * inetd. If we are to act as a master-server then we * detach by default. If we are invoked by inetd then * do not detach. If no arguments are specified then * we imply a -I option (the new fax protocol) and do * not want to detach. The logic is a touch convoluted * to do this correctly and is probably not worth the * effort (except to reduce configuration errors). */ fxStr queueDir(FAX_SPOOLDIR); int detach = -1; // unknown state while ((c = Sys::getopt(argc, argv, opts)) != -1) switch (c) { case 'h': case 'i': case 'o': case 's': case 'u': if (detach == -1) // detach unless explicitly specified detach = true; break; case 'H': case 'I': case 'O': case 'S': if (detach == -1) // don't detach when invoked by inetd detach = false; break; case 'd': detach = false; break; case 'q': queueDir = optarg; break; case '?': usage(appName); } if (detach == -1) // no protocol options means -I detach = false; if (Sys::chdir(queueDir) < 0) fatal("Can not change directory to %s", (const char*)queueDir); CheckSpoolingSetup(); if (detach) detachFromTTY(); /* * Rescan the arguments and create the appropriate * protocol support threads. We do this after the * above work for reasons I can no longer remember. */ optind = 1; opterr = 0; while ((c = Sys::getopt(argc, argv, opts)) != -1) switch (c) {#ifdef OLDPROTO_SUPPORT case 'o': handlers.append(new OldProtocolSuperServer(optarg)); break; case 'O': { OldProtocolServer* server = new OldProtocolServer; server->open(); handlers.append(server); } break;#else case 'o': case 'O': fatal("No support for old protocol"); /*NOTREACHED*/#endif#ifdef HTTP_SUPPORT case 'h': handlers.append(new HTTPSuperServer(optarg)); break; case 'H': { HTTPFaxServer* server = new HTTPFaxServer; server->open(); handlers.append(server); } break;#else case 'h': case 'H': fatal("No HTTP suport"); /*NOTREACHED*/#endif case 'l': bindaddress = strdup(optarg); break; case 'i': { InetSuperServer* iss; iss = new InetSuperServer(optarg); handlers.append(iss); if ((iss!=NULL) && (bindaddress!=NULL)) iss->setBindAddress(bindaddress); } break; case 'I': newInetServer(); break;#ifdef SNPP_SUPPORT case 's': handlers.append(new SNPPSuperServer(optarg)); break; case 'S': { SNPPServer* server = new SNPPServer; server->open(); handlers.append(server); } break;#else case 's': case 'S': fatal("No SNPP support"); /*NOTREACHED*/#endif#if CONFIG_UNIXTRANSPORT case 'u': handlers.append(new UnixSuperServer(optarg)); break;#else case 'u': fatal("No support for Unix domain sockets"); /*NOTREACHED*/#endif } if (handlers.length() == 0) newInetServer(); /* * Startup protocol processing. */ if (setjmp(problem) == 0) { signal(SIGHUP, fxSIGHANDLER(sigCleanup)); signal(SIGINT, fxSIGHANDLER(sigCleanup)); signal(SIGQUIT, fxSIGHANDLER(sigCleanup)); signal(SIGILL, fxSIGHANDLER(sigCleanup)); signal(SIGKILL, fxSIGHANDLER(sigCleanup)); signal(SIGBUS, fxSIGHANDLER(sigCleanup)); signal(SIGSEGV, fxSIGHANDLER(sigCleanup)); for (;;) Dispatcher::instance().dispatch(); } /* * We explicitly destroy protocol threads so that any * resources are reclaimed (e.g. Unix domain sockets). */ for (u_int i = 0, n = handlers.length(); i < n; i++) delete handlers[i]; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -