1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
/* $Id$ */
/*
* 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 "Sys.h"
#include "Dispatcher.h"
#include "HylaFAXServer.h"
#include "SuperServer.h"
#include "Socket.h"
#define MAXTRIES 10
SuperServer::SuperServer(const char* k, int bl) : kind(k)
{
backlog = bl;
ntries = 0;
Dispatcher::instance().startTimer(0,1,this); // schedule setup
}
SuperServer::~SuperServer() {}
void
SuperServer::timerExpired(long, long)
{
if (!startServer()) {
if (++ntries >= MAXTRIES) {
logError("HylaFAX %s: Unable to init server, "
"giving up after %u tries.", (const char*) kind, ntries);
return;
}
logNotice("HylaFAX %s: Unable to init server, "
"trying again in %u seconds.", (const char*) kind, 5*ntries);
Dispatcher::instance().startTimer(5*ntries,0, this);
} else
logNotice("HylaFAX %s Protocol Server: restarted.", (const char*) kind);
}
int
SuperServer::inputReady(int fd)
{
Socket::Address addr;
socklen_t slen = sizeof(addr);
int c = Socket::accept(fd, &addr, &slen);
if (c < 0) {
if (errno == EINTR || errno == ECONNABORTED)
return (0);
logError("HylaFAX %s: accept: %m", (const char*) kind);
_exit(-1);
}
#ifdef IPV6_ADDRFORM
if (Socket::family(addr) == AF_INET6) {
struct in6_addr& a = addr.in6.sin6_addr;
if ( (a.s6_addr32[0] == 0 && a.s6_addr32[1] == 0 && a.s6_addr32[2] == htonl(0xFFFF)) ||
(a.s6_addr32[0] == 0 && a.s6_addr32[1] == 0 && a.s6_addr32[2] == 0 && ntohl(a.s6_addr32[3]) > 1) ) {
logDebug("IPv4 address in AF_INET6, forcing AF_INET");
int af = AF_INET;
setsockopt(c, IPPROTO_IPV6, IPV6_ADDRFORM, &af, sizeof(af));
}
}
#endif
pid_t pid = fork();
switch (pid) {
case 0: // child
/*
* Child process, setup to process protocol requests.
* We unlink the dispatcher hook to this code and
* setup the link to the main handler that processes
* protocol requests. This routine is dispatched
* when data is received on stdin (for compatibility
* with servers started via inetd).
*/
HylaFAXServer* app; app = newChild(); // XXX for __GNUC__
Dispatcher::instance().unlink(fd);
HylaFAXServer::closeLogging(); // close any open syslog fd
HylaFAXServer::closeAllDispatched();
Sys::close(STDERR_FILENO);
if (dup2(c, STDIN_FILENO) < 0 || dup2(c, STDOUT_FILENO) < 0) {
logError("HylaFAX %s: dup2: %m", (const char*) kind);
_exit(-1);
}
if (c != STDIN_FILENO && c != STDOUT_FILENO)
Sys::close(c);
HylaFAXServer::setupLogging(); // reopen syslog before chroot
app->open(); // opening greeting
break;
case -1: // fork failure
logError("HylaFAX %s: Cannot fork: %m", (const char*) kind);
break;
default: // parent
Sys::close(c);
Dispatcher::instance().startChild(pid, this);
break;
}
return (0); // indicate data was consumed
}
void
SuperServer::childStatus(pid_t, int)
{
/*
* Nothing to do here - childStatus means it's already been reaped, and
* thus off the queue from the Dispatcher
*/
}
|