kopia lustrzana https://gitlab.com/sane-project/backends
Add standalone daemon mode, building upon the AF-indep/IPv6 debug mode.
Reorganize code by splitting the main() function into a series of functions. Factorize common code between the old network code and the AF-indep code. There's now only one version of main().merge-requests/1/head
rodzic
ef2838234e
commit
9c6fea1943
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
2008-04-06 Julien Blache <jb@jblache.org>
|
||||||
|
* frontend/saned.c: add standalone daemon mode, building upon the
|
||||||
|
AF-indep/IPv6 debug mode. Reorganize code by splitting the main()
|
||||||
|
function into a series of functions. Factorize common code between
|
||||||
|
the old network code and the AF-indep code. There's now only one
|
||||||
|
version of main().
|
||||||
|
* doc/saned.man: document new -a flag, reorganize manpage
|
||||||
|
sections (separate inetd configuration under the INETD
|
||||||
|
CONFIGURATION section).
|
||||||
|
|
||||||
2008-04-05 Stéphane Voltz <stef.dev@free.fr>
|
2008-04-05 Stéphane Voltz <stef.dev@free.fr>
|
||||||
* backend/genesys.c backend/genesys.h backend/genesys_devices.c
|
* backend/genesys.c backend/genesys.h backend/genesys_devices.c
|
||||||
backend/genesys_gl646.c backend/genesys_low.h:
|
backend/genesys_gl646.c backend/genesys_low.h:
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
.TH saned 8 "30 May 2004" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
.TH saned 8 "6 April 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||||
.IX saned
|
.IX saned
|
||||||
.SH NAME
|
.SH NAME
|
||||||
saned \- SANE network daemon
|
saned \- SANE network daemon
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B saned
|
.B saned
|
||||||
.RB [ -d | -s
|
.B [ -a | -d
|
||||||
.RI [ n ]]
|
.I [ n ]
|
||||||
|
.B | -s
|
||||||
|
.I [ n ]
|
||||||
|
.B ]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B saned
|
.B saned
|
||||||
is the SANE (Scanner Access Now Easy) daemon that allows remote clients
|
is the SANE (Scanner Access Now Easy) daemon that allows remote clients
|
||||||
|
@ -13,6 +16,19 @@ to access image acquisition devices available on the local host.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
|
.B -a
|
||||||
|
flag requests that
|
||||||
|
.B saned
|
||||||
|
run in standalone daemon mode. In this mode,
|
||||||
|
.B saned
|
||||||
|
will detach from the console and run in the background, listening for incoming
|
||||||
|
client connections;
|
||||||
|
.B inetd
|
||||||
|
is not required for
|
||||||
|
.B saned
|
||||||
|
operations in this mode.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
.B -d
|
.B -d
|
||||||
and
|
and
|
||||||
.B -s
|
.B -s
|
||||||
|
@ -80,10 +96,11 @@ scan-client.somedomain.firm
|
||||||
.PP
|
.PP
|
||||||
The case of the host names does not matter, so AHost.COM is considered
|
The case of the host names does not matter, so AHost.COM is considered
|
||||||
identical to ahost.com.
|
identical to ahost.com.
|
||||||
|
.SH INETD CONFIGURATION
|
||||||
For
|
For
|
||||||
.B saned
|
.B saned
|
||||||
to work properly, it is also necessary to add a configuration line to
|
to work properly in its default mode of operation, it is also necessary to add
|
||||||
|
a configuration line to
|
||||||
.IR /etc/inetd.conf .
|
.IR /etc/inetd.conf .
|
||||||
Note that your inetd must support IPv6 if you
|
Note that your inetd must support IPv6 if you
|
||||||
want to connect to saned over IPv6 ; xinetd and openbsd-inetd are known to
|
want to connect to saned over IPv6 ; xinetd and openbsd-inetd are known to
|
||||||
|
@ -152,7 +169,11 @@ The official IANA short name for port 6566 is "sane-port". The older name "sane"
|
||||||
is now deprecated.
|
is now deprecated.
|
||||||
|
|
||||||
.SH "RESTRICTIONS"
|
.SH "RESTRICTIONS"
|
||||||
In addition to the control connection (port 6566) saned also uses a data
|
In addition to the control connection (port
|
||||||
|
.B 6566
|
||||||
|
)
|
||||||
|
.B saned
|
||||||
|
also uses a data
|
||||||
connection. The port of this socket is selected by the operating system and
|
connection. The port of this socket is selected by the operating system and
|
||||||
can't be specified by the user currently. This may be a problem if the
|
can't be specified by the user currently. This may be a problem if the
|
||||||
connection must go through a firewall (packet filter). If you must use a packet
|
connection must go through a firewall (packet filter). If you must use a packet
|
||||||
|
|
701
frontend/saned.c
701
frontend/saned.c
|
@ -1,8 +1,8 @@
|
||||||
/* sane - Scanner Access Now Easy.
|
/* sane - Scanner Access Now Easy.
|
||||||
Copyright (C) 1997 Andreas Beck
|
Copyright (C) 1997 Andreas Beck
|
||||||
Copyright (C) 2001 - 2004 Henning Meier-Geinitz
|
Copyright (C) 2001 - 2004 Henning Meier-Geinitz
|
||||||
Copyright (C) 2003 Julien BLACHE <jb@jblache.org>
|
Copyright (C) 2003, 2008 Julien BLACHE <jb@jblache.org>
|
||||||
AF-independent + IPv6 code
|
AF-independent + IPv6 code, standalone mode
|
||||||
|
|
||||||
This file is part of the SANE package.
|
This file is part of the SANE package.
|
||||||
|
|
||||||
|
@ -76,13 +76,14 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#ifdef SANED_USES_AF_INDEP
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
|
#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
|
||||||
# include <sys/poll.h>
|
# include <sys/poll.h>
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* This replacement poll() using select() is only designed to cover
|
* This replacement poll() using select() is only designed to cover
|
||||||
* our needs in main(). It should probably be extended...
|
* our needs in run_standalone(). It should probably be extended...
|
||||||
*/
|
*/
|
||||||
struct pollfd
|
struct pollfd
|
||||||
{
|
{
|
||||||
|
@ -92,34 +93,44 @@ struct pollfd
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POLLIN 0x0001
|
#define POLLIN 0x0001
|
||||||
|
#define POLLERR 0x0002
|
||||||
|
|
||||||
|
int
|
||||||
|
poll (struct pollfd *ufds, unsigned int nfds, int timeout);
|
||||||
|
|
||||||
int
|
int
|
||||||
poll (struct pollfd *ufds, unsigned int nfds, int timeout)
|
poll (struct pollfd *ufds, unsigned int nfds, int timeout)
|
||||||
{
|
{
|
||||||
struct pollfd *fdp;
|
struct pollfd *fdp;
|
||||||
|
|
||||||
fd_set fds;
|
fd_set rfds;
|
||||||
|
fd_set efds;
|
||||||
|
struct timeval tv;
|
||||||
int maxfd = 0;
|
int maxfd = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* unused */
|
tv.tv_sec = timeout / 1000;
|
||||||
timeout = timeout;
|
tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
|
||||||
|
|
||||||
FD_ZERO (&fds);
|
FD_ZERO (&rfds);
|
||||||
|
FD_ZERO (&efds);
|
||||||
|
|
||||||
for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
|
for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
|
||||||
{
|
{
|
||||||
|
fdp->revents = 0;
|
||||||
|
|
||||||
if (fdp->events & POLLIN)
|
if (fdp->events & POLLIN)
|
||||||
{
|
FD_SET (fdp->fd, &rfds);
|
||||||
FD_SET (fdp->fd, &fds);
|
|
||||||
|
FD_SET (fdp->fd, &efds);
|
||||||
|
|
||||||
maxfd = (fdp->fd > maxfd) ? fdp->fd : maxfd;
|
maxfd = (fdp->fd > maxfd) ? fdp->fd : maxfd;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
maxfd++;
|
maxfd++;
|
||||||
|
|
||||||
ret = select (maxfd, &fds, NULL, NULL, NULL);
|
ret = select (maxfd, &rfds, NULL, &efds, &tv);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -127,14 +138,16 @@ poll (struct pollfd *ufds, unsigned int nfds, int timeout)
|
||||||
for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
|
for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
|
||||||
{
|
{
|
||||||
if (fdp->events & POLLIN)
|
if (fdp->events & POLLIN)
|
||||||
if (FD_ISSET (fdp->fd, &fds))
|
if (FD_ISSET (fdp->fd, &rfds))
|
||||||
fdp->revents = POLLIN;
|
fdp->revents |= POLLIN;
|
||||||
|
|
||||||
|
if (FD_ISSET (fdp->fd, &efds))
|
||||||
|
fdp->revents |= POLLERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_SYS_POLL_H && HAVE_POLL */
|
#endif /* HAVE_SYS_POLL_H && HAVE_POLL */
|
||||||
#endif /* SANED_USES_AF_INDEP */
|
|
||||||
|
|
||||||
#include "../include/sane/sane.h"
|
#include "../include/sane/sane.h"
|
||||||
#include "../include/sane/sanei.h"
|
#include "../include/sane/sanei.h"
|
||||||
|
@ -169,8 +182,19 @@ poll (struct pollfd *ufds, unsigned int nfds, int timeout)
|
||||||
# define MAXHOSTNAMELEN 120
|
# define MAXHOSTNAMELEN 120
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct saned_child {
|
||||||
|
pid_t pid;
|
||||||
|
struct saned_child *next;
|
||||||
|
};
|
||||||
|
struct saned_child *children;
|
||||||
|
int numchildren;
|
||||||
|
|
||||||
#define SANED_CONFIG_FILE "saned.conf"
|
#define SANED_CONFIG_FILE "saned.conf"
|
||||||
|
|
||||||
|
#define SANED_SERVICE_NAME "sane-port"
|
||||||
|
#define SANED_SERVICE_PORT 6566
|
||||||
|
#define SANED_SERVICE_PORT_S "6566"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u_int inuse:1; /* is this handle in use? */
|
u_int inuse:1; /* is this handle in use? */
|
||||||
|
@ -186,6 +210,7 @@ static int can_authorize;
|
||||||
static Wire wire;
|
static Wire wire;
|
||||||
static int num_handles;
|
static int num_handles;
|
||||||
static int debug;
|
static int debug;
|
||||||
|
static int run_mode;
|
||||||
static Handle *handle;
|
static Handle *handle;
|
||||||
static union
|
static union
|
||||||
{
|
{
|
||||||
|
@ -220,6 +245,11 @@ static SANE_Bool log_to_syslog = SANE_TRUE;
|
||||||
/* forward declarations: */
|
/* forward declarations: */
|
||||||
static void process_request (Wire * w);
|
static void process_request (Wire * w);
|
||||||
|
|
||||||
|
#define SANED_RUN_INETD 0
|
||||||
|
#define SANED_RUN_DEBUG 1
|
||||||
|
#define SANED_RUN_ALONE 2
|
||||||
|
|
||||||
|
|
||||||
#define DBG_ERR 1
|
#define DBG_ERR 1
|
||||||
#define DBG_WARN 2
|
#define DBG_WARN 2
|
||||||
#define DBG_MSG 3
|
#define DBG_MSG 3
|
||||||
|
@ -399,6 +429,7 @@ quit (int signum)
|
||||||
if (handle)
|
if (handle)
|
||||||
free (handle);
|
free (handle);
|
||||||
DBG (DBG_WARN, "quit: exiting\n");
|
DBG (DBG_WARN, "quit: exiting\n");
|
||||||
|
if (log_to_syslog)
|
||||||
closelog ();
|
closelog ();
|
||||||
exit (EXIT_SUCCESS); /* This is a nowait-daemon. */
|
exit (EXIT_SUCCESS); /* This is a nowait-daemon. */
|
||||||
}
|
}
|
||||||
|
@ -2035,56 +2066,178 @@ process_request (Wire * w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SANED_USES_AF_INDEP
|
|
||||||
int
|
static int
|
||||||
main (int argc, char *argv[])
|
wait_child (pid_t pid, int *status, int options)
|
||||||
|
{
|
||||||
|
struct saned_child *c;
|
||||||
|
struct saned_child *p = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = waitpid(pid, status, options);
|
||||||
|
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (c = children; (c != NULL) && (c->next != NULL); p = c, c = c->next)
|
||||||
|
{
|
||||||
|
if (c->pid == ret)
|
||||||
|
{
|
||||||
|
if (c == children)
|
||||||
|
children = c->next;
|
||||||
|
else if (p != NULL)
|
||||||
|
p->next = c->next;
|
||||||
|
|
||||||
|
free(c);
|
||||||
|
|
||||||
|
numchildren--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_child (pid_t pid)
|
||||||
|
{
|
||||||
|
struct saned_child *c;
|
||||||
|
|
||||||
|
c = (struct saned_child *) malloc (sizeof(struct saned_child));
|
||||||
|
|
||||||
|
if (c == NULL)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "add_child: out of memory\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->pid = pid;
|
||||||
|
c->next = children;
|
||||||
|
|
||||||
|
children = c;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_connection (int fd)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
|
||||||
int on = 1;
|
|
||||||
#ifdef TCP_NODELAY
|
#ifdef TCP_NODELAY
|
||||||
int level = -1;
|
int level = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
debug = DBG_WARN;
|
DBG (DBG_DBG, "handle_connection: processing client connection\n");
|
||||||
openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
|
|
||||||
|
|
||||||
prog_name = strrchr (argv[0], '/');
|
wire.io.fd = fd;
|
||||||
if (prog_name)
|
|
||||||
++prog_name;
|
|
||||||
else
|
|
||||||
prog_name = argv[0];
|
|
||||||
|
|
||||||
byte_order.w = 0;
|
signal (SIGALRM, quit);
|
||||||
byte_order.ch = 1;
|
signal (SIGPIPE, quit);
|
||||||
|
|
||||||
sanei_w_init (&wire, sanei_codec_bin_init);
|
#ifdef TCP_NODELAY
|
||||||
wire.io.read = read;
|
# ifdef SOL_TCP
|
||||||
wire.io.write = write;
|
level = SOL_TCP;
|
||||||
|
# else /* !SOL_TCP */
|
||||||
if (argc == 2 &&
|
/* Look up the protocol level in the protocols database. */
|
||||||
(strncmp (argv[1], "-d", 2) == 0 || strncmp (argv[1], "-s", 2) == 0))
|
{
|
||||||
|
struct protoent *p;
|
||||||
|
p = getprotobyname ("tcp");
|
||||||
|
if (p == 0)
|
||||||
|
{
|
||||||
|
DBG (DBG_WARN, "handle_connection: cannot look up `tcp' protocol number");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
level = p->p_proto;
|
||||||
|
}
|
||||||
|
# endif /* SOL_TCP */
|
||||||
|
if (level == -1
|
||||||
|
|| setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on)))
|
||||||
|
DBG (DBG_WARN, "handle_connection: failed to put socket in TCP_NODELAY mode (%s)",
|
||||||
|
strerror (errno));
|
||||||
|
#endif /* !TCP_NODELAY */
|
||||||
|
|
||||||
|
if (init (&wire) < 0)
|
||||||
|
quit (0);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
reset_watchdog ();
|
||||||
|
process_request (&wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_client (int fd)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "handle_client: spawning child process\n");
|
||||||
|
|
||||||
|
pid = fork ();
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
/* child */
|
||||||
|
handle_connection (fd);
|
||||||
|
}
|
||||||
|
else if (pid > 0)
|
||||||
|
{
|
||||||
|
/* parent */
|
||||||
|
add_child (pid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FAILED */
|
||||||
|
DBG (DBG_ERR, "handle_client: fork() failed: %s\n", strerror (errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bail_out (int error)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "%sbailing out, waiting for children...\n", (error) ? "FATAL ERROR; " : "");
|
||||||
|
|
||||||
|
while (numchildren > 0)
|
||||||
|
wait_child (-1, NULL, 0);
|
||||||
|
|
||||||
|
DBG (DBG_ERR, "bail_out: all children exited\n");
|
||||||
|
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sig_int_term_handler (int signum);
|
||||||
|
|
||||||
|
void
|
||||||
|
sig_int_term_handler (int signum)
|
||||||
|
{
|
||||||
|
/* unused */
|
||||||
|
signum = signum;
|
||||||
|
|
||||||
|
signal (SIGINT, NULL);
|
||||||
|
signal (SIGTERM, NULL);
|
||||||
|
|
||||||
|
bail_out (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SANED_USES_AF_INDEP
|
||||||
|
static void
|
||||||
|
do_bindings (int *nfds, struct pollfd **fds)
|
||||||
{
|
{
|
||||||
/* don't operate in daemon mode: wait for connection request: */
|
|
||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
struct addrinfo *resp;
|
struct addrinfo *resp;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct pollfd *fds = NULL;
|
|
||||||
struct pollfd *fdp = NULL;
|
struct pollfd *fdp = NULL;
|
||||||
int nfds;
|
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
short sane_port;
|
short sane_port;
|
||||||
int family;
|
int family;
|
||||||
|
int fd = -1;
|
||||||
|
int on = 1;
|
||||||
|
|
||||||
if (argv[1][2])
|
DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getaddrinfo)\n", SANED_SERVICE_NAME);
|
||||||
debug = atoi (argv[1] + 2);
|
|
||||||
if (strncmp (argv[1], "-d", 2) == 0)
|
|
||||||
log_to_syslog = SANE_FALSE;
|
|
||||||
|
|
||||||
DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
|
|
||||||
|
|
||||||
DBG (DBG_DBG,
|
|
||||||
"main: trying to get port for service `sane-port' (getaddrinfo)\n");
|
|
||||||
|
|
||||||
memset (&hints, 0, sizeof (struct addrinfo));
|
memset (&hints, 0, sizeof (struct addrinfo));
|
||||||
|
|
||||||
|
@ -2092,34 +2245,33 @@ main (int argc, char *argv[])
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
err = getaddrinfo (NULL, "sane-port", &hints, &res);
|
err = getaddrinfo (NULL, SANED_SERVICE_NAME, &hints, &res);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG (DBG_WARN, "main: \"sane-port\" service unknown on your host; you should add\n");
|
DBG (DBG_WARN, "do_bindings: \" %s \" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
|
||||||
DBG (DBG_WARN, "main: sane-port 6566/tcp saned # SANE network scanner daemon\n");
|
DBG (DBG_WARN, "do_bindings: %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
|
||||||
DBG (DBG_WARN, "main: to your /etc/services file (or equivalent). Proceeding anyway.\n");
|
DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
|
||||||
err = getaddrinfo (NULL, "6566", &hints, &res);
|
err = getaddrinfo (NULL, SANED_SERVICE_PORT_S, &hints, &res);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: getaddrinfo() failed even with numeric port: %s\n",
|
DBG (DBG_ERR, "do_bindings: getaddrinfo() failed even with numeric port: %s\n", gai_strerror (err));
|
||||||
gai_strerror (err));
|
bail_out (1);
|
||||||
exit (1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (resp = res, nfds = 0; resp != NULL; resp = resp->ai_next, nfds++)
|
for (resp = res, *nfds = 0; resp != NULL; resp = resp->ai_next, (*nfds)++)
|
||||||
;
|
;
|
||||||
|
|
||||||
fds = malloc (nfds * sizeof (struct pollfd));
|
*fds = malloc (*nfds * sizeof (struct pollfd));
|
||||||
|
|
||||||
if (fds == NULL)
|
if (fds == NULL)
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: not enough memory for fds\n");
|
DBG (DBG_ERR, "do_bindings: not enough memory for fds\n");
|
||||||
freeaddrinfo (res);
|
freeaddrinfo (res);
|
||||||
exit (1);
|
bail_out (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (resp = res, i = 0, fdp = fds; resp != NULL; resp = resp->ai_next, i++, fdp++)
|
for (resp = res, i = 0, fdp = *fds; resp != NULL; resp = resp->ai_next, i++, fdp++)
|
||||||
{
|
{
|
||||||
if (resp->ai_family == AF_INET)
|
if (resp->ai_family == AF_INET)
|
||||||
{
|
{
|
||||||
|
@ -2136,28 +2288,26 @@ main (int argc, char *argv[])
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fdp--;
|
fdp--;
|
||||||
nfds--;
|
(*nfds)--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: [%d] socket () using IPv%d\n", i, family);
|
DBG (DBG_DBG, "do_bindings: [%d] socket () using IPv%d\n", i, family);
|
||||||
if ((fd = socket (resp->ai_family, SOCK_STREAM, 0)) < 0)
|
if ((fd = socket (resp->ai_family, SOCK_STREAM, 0)) < 0)
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: [%d] socket failed: %s\n", i,
|
DBG (DBG_ERR, "do_bindings: [%d] socket failed: %s\n", i, strerror (errno));
|
||||||
strerror (errno));
|
|
||||||
|
|
||||||
nfds--;
|
|
||||||
fdp--;
|
fdp--;
|
||||||
|
(*nfds)--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: [%d] setsockopt ()\n", i);
|
DBG (DBG_DBG, "do_bindings: [%d] setsockopt ()\n", i);
|
||||||
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
|
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
|
||||||
DBG (DBG_ERR, "main: [%d] failed to put socket in SO_REUSEADDR mode (%s)\n",
|
DBG (DBG_ERR, "do_bindings: [%d] failed to put socket in SO_REUSEADDR mode (%s)\n", i, strerror (errno));
|
||||||
i, strerror (errno));
|
|
||||||
|
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: [%d] bind () to port %d\n", i, sane_port);
|
DBG (DBG_DBG, "do_bindings: [%d] bind () to port %d\n", i, sane_port);
|
||||||
if (bind (fd, resp->ai_addr, resp->ai_addrlen) < 0)
|
if (bind (fd, resp->ai_addr, resp->ai_addrlen) < 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -2168,20 +2318,25 @@ main (int argc, char *argv[])
|
||||||
* is not functional on this machine.
|
* is not functional on this machine.
|
||||||
* In any case, a bind() call returning an error is not necessarily fatal.
|
* In any case, a bind() call returning an error is not necessarily fatal.
|
||||||
*/
|
*/
|
||||||
DBG (DBG_ERR, "main: [%d] bind failed: %s\n", i, strerror (errno));
|
DBG (DBG_WARN, "do_bindings: [%d] bind failed: %s\n", i, strerror (errno));
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
|
|
||||||
nfds--;
|
|
||||||
fdp--;
|
fdp--;
|
||||||
|
(*nfds)--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: [%d] listen ()\n", i);
|
DBG (DBG_DBG, "do_bindings: [%d] listen ()\n", i);
|
||||||
if (listen (fd, 1) < 0)
|
if (listen (fd, 1) < 0)
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: [%d] listen failed: %s\n", i, strerror (errno));
|
DBG (DBG_ERR, "do_bindings: [%d] listen failed: %s\n", i, strerror (errno));
|
||||||
exit (1);
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
fdp--;
|
||||||
|
(*nfds)--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdp->fd = fd;
|
fdp->fd = fd;
|
||||||
|
@ -2191,121 +2346,212 @@ main (int argc, char *argv[])
|
||||||
resp = NULL;
|
resp = NULL;
|
||||||
freeaddrinfo (res);
|
freeaddrinfo (res);
|
||||||
|
|
||||||
if (nfds <= 0)
|
if (*nfds <= 0)
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: couldn't bind an address. Exiting.\n");
|
DBG (DBG_ERR, "do_bindings: couldn't bind an address. Exiting.\n");
|
||||||
|
bail_out (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !SANED_USES_AF_INDEP */
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_bindings (int *nfds, struct pollfd **fds)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
struct servent *serv;
|
||||||
|
short port;
|
||||||
|
int fd = -1;
|
||||||
|
int on = 1;
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getservbyname)\n", SANED_SERVICE_PORT);
|
||||||
|
serv = getservbyname (SANED_SERVICE_NAME, "tcp");
|
||||||
|
|
||||||
|
if (serv)
|
||||||
|
{
|
||||||
|
port = serv->s_port;
|
||||||
|
DBG (DBG_MSG, "main: port is %d\n", ntohs (port));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port = htons (SANED_SERVICE_PORT);
|
||||||
|
DBG (DBG_WARN, "do_bindings: \"%s\" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
|
||||||
|
DBG (DBG_WARN, "do_bindings: %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
|
||||||
|
DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
*nfds = 1;
|
||||||
|
*fds = malloc (*nfds * sizeof (struct pollfd));
|
||||||
|
|
||||||
|
if (fds == NULL)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "do_bindings: not enough memory for fds\n");
|
||||||
|
bail_out (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&sin, 0, sizeof (sin));
|
||||||
|
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
sin.sin_port = port;
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "do_bindings: socket ()\n");
|
||||||
|
fd = socket (AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "do_bindings: setsockopt ()\n");
|
||||||
|
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
|
||||||
|
DBG (DBG_ERR, "do_bindings: failed to put socket in SO_REUSEADDR mode (%s)", strerror (errno));
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "do_bindings: bind ()\n");
|
||||||
|
if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "do_bindings: bind failed: %s", strerror (errno));
|
||||||
|
bail_out (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG (DBG_DBG, "do_bindings: listen ()\n");
|
||||||
|
if (listen (fd, 1) < 0)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "do_bindings: listen failed: %s", strerror (errno));
|
||||||
|
bail_out (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*fds)->fd = fd;
|
||||||
|
(*fds)->events = POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SANED_USES_AF_INDEP */
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_standalone (int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct pollfd *fds = NULL;
|
||||||
|
struct pollfd *fdp = NULL;
|
||||||
|
int nfds;
|
||||||
|
int fd;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Unused in this function */
|
||||||
|
argc = argc;
|
||||||
|
argv = argv;
|
||||||
|
|
||||||
|
do_bindings (&nfds, &fds);
|
||||||
|
|
||||||
|
if (run_mode != SANED_RUN_DEBUG)
|
||||||
|
{
|
||||||
|
DBG (DBG_MSG, "run_standalone: daemonizing now\n");
|
||||||
|
|
||||||
|
if (daemon (0, 0) != 0)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "FATAL ERROR: cannot daemonize: %s\n", strerror (errno));
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG (DBG_MSG, "main: waiting for control connection\n");
|
signal(SIGINT, sig_int_term_handler);
|
||||||
|
signal(SIGTERM, sig_int_term_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG (DBG_MSG, "run_standalone: waiting for control connection\n");
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (poll (fds, nfds, -1) < 0)
|
ret = poll (fds, nfds, 500);
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: poll failed: %s\n", strerror (errno));
|
DBG (DBG_ERR, "run_standalone: poll failed: %s\n", strerror (errno));
|
||||||
free (fds);
|
free (fds);
|
||||||
exit (1);
|
bail_out (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait for children */
|
||||||
|
while (wait_child (-1, NULL, WNOHANG) > 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
|
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
|
||||||
{
|
{
|
||||||
|
/* Error on an fd */
|
||||||
if (! (fdp->revents & POLLIN))
|
if (! (fdp->revents & POLLIN))
|
||||||
continue;
|
|
||||||
|
|
||||||
wire.io.fd = accept (fdp->fd, 0, 0);
|
|
||||||
if (wire.io.fd < 0)
|
|
||||||
{
|
{
|
||||||
DBG (DBG_ERR, "main: accept failed: %s", strerror (errno));
|
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
|
||||||
|
close (fdp->fd);
|
||||||
|
|
||||||
free (fds);
|
free (fds);
|
||||||
exit (1);
|
|
||||||
|
DBG (DBG_WARN, "run_standalone: invalid fd in set, attempting to re-bind\n");
|
||||||
|
|
||||||
|
/* Reopen sockets */
|
||||||
|
do_bindings (&nfds, &fds);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = accept (fdp->fd, 0, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
DBG (DBG_ERR, "run_standalone: accept failed: %s", strerror (errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_mode == SANED_RUN_DEBUG)
|
||||||
|
{
|
||||||
|
handle_connection (fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
handle_client (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_mode == SANED_RUN_DEBUG)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
|
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
|
||||||
close (fdp->fd);
|
close (fdp->fd);
|
||||||
|
|
||||||
free (fds);
|
free (fds);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
static void
|
||||||
break;
|
run_inetd (int argc, char **argv)
|
||||||
}
|
{
|
||||||
}
|
int fd = 1;
|
||||||
else
|
|
||||||
/* use filedescriptor opened by inetd: */
|
#ifndef HAVE_OS2_H
|
||||||
#ifdef HAVE_OS2_H
|
/* Unused in this function */
|
||||||
|
argc = argc;
|
||||||
|
argv = argv;
|
||||||
|
|
||||||
|
#else
|
||||||
/* under OS/2, the socket handle is passed as argument on the command
|
/* under OS/2, the socket handle is passed as argument on the command
|
||||||
line; the socket handle is relative to IBM TCP/IP, so a call
|
line; the socket handle is relative to IBM TCP/IP, so a call
|
||||||
to impsockethandle() is required to add it to the EMX runtime */
|
to impsockethandle() is required to add it to the EMX runtime */
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
wire.io.fd = _impsockhandle (atoi (argv[1]), 0);
|
fd = _impsockhandle (atoi (argv[1]), 0);
|
||||||
if (wire.io.fd == -1)
|
if (fd == -1)
|
||||||
perror ("impsockhandle");
|
perror ("impsockhandle");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif /* HAVE_OS2_H */
|
#endif /* HAVE_OS2_H */
|
||||||
wire.io.fd = 1;
|
|
||||||
|
|
||||||
signal (SIGALRM, quit);
|
handle_connection(fd);
|
||||||
signal (SIGPIPE, quit);
|
|
||||||
|
|
||||||
#ifdef TCP_NODELAY
|
|
||||||
# ifdef SOL_TCP
|
|
||||||
level = SOL_TCP;
|
|
||||||
# else /* !SOL_TCP */
|
|
||||||
/* Look up the protocol level in the protocols database. */
|
|
||||||
{
|
|
||||||
struct protoent *p;
|
|
||||||
p = getprotobyname ("tcp");
|
|
||||||
if (p == 0)
|
|
||||||
{
|
|
||||||
DBG (DBG_WARN, "main: cannot look up `tcp' protocol number");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
level = p->p_proto;
|
|
||||||
}
|
|
||||||
# endif /* SOL_TCP */
|
|
||||||
if (level == -1
|
|
||||||
|| setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on)))
|
|
||||||
DBG (DBG_WARN, "main: failed to put socket in TCP_NODELAY mode (%s)",
|
|
||||||
strerror (errno));
|
|
||||||
#endif /* !TCP_NODELAY */
|
|
||||||
|
|
||||||
/* define the version string depending on which network code is used */
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
DBG (DBG_WARN, "saned (AF-indep+IPv6) from %s ready\n", PACKAGE_STRING);
|
|
||||||
#else
|
|
||||||
DBG (DBG_WARN, "saned (AF-indep) from %s ready\n", PACKAGE_STRING);
|
|
||||||
#endif /* ENABLE_IPV6 */
|
|
||||||
|
|
||||||
if (init (&wire) < 0)
|
|
||||||
quit (0);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
reset_watchdog ();
|
|
||||||
process_request (&wire);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !SANED_USES_AF_INDEP */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int fd, on = 1;
|
|
||||||
#ifdef TCP_NODELAY
|
|
||||||
int level = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debug = DBG_WARN;
|
debug = DBG_WARN;
|
||||||
openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
|
|
||||||
|
|
||||||
prog_name = strrchr (argv[0], '/');
|
prog_name = strrchr (argv[0], '/');
|
||||||
if (prog_name)
|
if (prog_name)
|
||||||
|
@ -2313,6 +2559,33 @@ main (int argc, char *argv[])
|
||||||
else
|
else
|
||||||
prog_name = argv[0];
|
prog_name = argv[0];
|
||||||
|
|
||||||
|
numchildren = 0;
|
||||||
|
run_mode = SANED_RUN_INETD;
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
{
|
||||||
|
if (strncmp (argv[1], "-a", 2) == 0)
|
||||||
|
run_mode = SANED_RUN_ALONE;
|
||||||
|
else if (strncmp (argv[1], "-d", 2) == 0)
|
||||||
|
{
|
||||||
|
run_mode = SANED_RUN_DEBUG;
|
||||||
|
log_to_syslog = SANE_FALSE;
|
||||||
|
}
|
||||||
|
else if (strncmp (argv[1], "-s", 2) == 0)
|
||||||
|
run_mode = SANED_RUN_DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_mode == SANED_RUN_DEBUG)
|
||||||
|
{
|
||||||
|
if (argv[1][2])
|
||||||
|
debug = atoi (argv[1] + 2);
|
||||||
|
|
||||||
|
DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_to_syslog)
|
||||||
|
openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
|
||||||
|
|
||||||
byte_order.w = 0;
|
byte_order.w = 0;
|
||||||
byte_order.ch = 1;
|
byte_order.ch = 1;
|
||||||
|
|
||||||
|
@ -2320,121 +2593,27 @@ main (int argc, char *argv[])
|
||||||
wire.io.read = read;
|
wire.io.read = read;
|
||||||
wire.io.write = write;
|
wire.io.write = write;
|
||||||
|
|
||||||
if (argc == 2 &&
|
/* define the version string depending on which network code is used */
|
||||||
(strncmp (argv[1], "-d", 2) == 0 || strncmp (argv[1], "-s", 2) == 0))
|
#ifdef SANED_USES_AF_INDEP
|
||||||
{
|
# ifdef ENABLE_IPV6
|
||||||
/* don't operate in daemon mode: wait for connection request: */
|
DBG (DBG_WARN, "saned (AF-indep+IPv6) from %s starting up\n", PACKAGE_STRING);
|
||||||
struct sockaddr_in sin;
|
# else
|
||||||
struct servent *serv;
|
DBG (DBG_WARN, "saned (AF-indep) from %s starting up\n", PACKAGE_STRING);
|
||||||
short port;
|
# endif /* ENABLE_IPV6 */
|
||||||
|
#else
|
||||||
if (argv[1][2])
|
|
||||||
debug = atoi (argv[1] + 2);
|
|
||||||
if (strncmp (argv[1], "-d", 2) == 0)
|
|
||||||
log_to_syslog = SANE_FALSE;
|
|
||||||
|
|
||||||
DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
|
|
||||||
|
|
||||||
memset (&sin, 0, sizeof (sin));
|
|
||||||
|
|
||||||
DBG (DBG_DBG,
|
|
||||||
"main: trying to get port for service `sane-port' (getservbyname)\n");
|
|
||||||
serv = getservbyname ("sane-port", "tcp");
|
|
||||||
if (serv)
|
|
||||||
{
|
|
||||||
port = serv->s_port;
|
|
||||||
DBG (DBG_MSG, "main: port is %d\n", ntohs (port));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
port = htons (6566);
|
|
||||||
DBG (DBG_WARN, "main: \"sane-port\" service unknown on your host; you should add\n");
|
|
||||||
DBG (DBG_WARN, "main: sane-port 6566/tcp saned # SANE network scanner daemon\n");
|
|
||||||
DBG (DBG_WARN, "main: to your /etc/services file (or equivalent). Proceeding anyway.\n");
|
|
||||||
}
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
sin.sin_port = port;
|
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: socket ()\n");
|
|
||||||
fd = socket (AF_INET, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: setsockopt ()\n");
|
|
||||||
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
|
|
||||||
DBG (DBG_ERR, "failed to put socket in SO_REUSEADDR mode (%s)",
|
|
||||||
strerror (errno));
|
|
||||||
|
|
||||||
DBG (DBG_DBG, "main: bind ()\n");
|
|
||||||
if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
|
|
||||||
{
|
|
||||||
DBG (DBG_ERR, "main: bind failed: %s", strerror (errno));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
DBG (DBG_DBG, "main: listen ()\n");
|
|
||||||
if (listen (fd, 1) < 0)
|
|
||||||
{
|
|
||||||
DBG (DBG_ERR, "main: listen failed: %s", strerror (errno));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
DBG (DBG_MSG, "main: waiting for control connection\n");
|
|
||||||
wire.io.fd = accept (fd, 0, 0);
|
|
||||||
if (wire.io.fd < 0)
|
|
||||||
{
|
|
||||||
DBG (DBG_ERR, "main: accept failed: %s", strerror (errno));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* use filedescriptor opened by inetd: */
|
|
||||||
#ifdef HAVE_OS2_H
|
|
||||||
/* under OS/2, the socket handle is passed as argument on the command
|
|
||||||
line; the socket handle is relative to IBM TCP/IP, so a call
|
|
||||||
to impsockethandle() is required to add it to the EMX runtime */
|
|
||||||
if (argc == 2)
|
|
||||||
{
|
|
||||||
wire.io.fd = _impsockhandle (atoi (argv[1]), 0);
|
|
||||||
if (wire.io.fd == -1)
|
|
||||||
perror ("impsockhandle");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* HAVE_OS2_H */
|
|
||||||
wire.io.fd = 1;
|
|
||||||
|
|
||||||
signal (SIGALRM, quit);
|
|
||||||
signal (SIGPIPE, quit);
|
|
||||||
|
|
||||||
#ifdef TCP_NODELAY
|
|
||||||
# ifdef SOL_TCP
|
|
||||||
level = SOL_TCP;
|
|
||||||
# else /* !SOL_TCP */
|
|
||||||
/* Look up the protocol level in the protocols database. */
|
|
||||||
{
|
|
||||||
struct protoent *p;
|
|
||||||
p = getprotobyname ("tcp");
|
|
||||||
if (p == 0)
|
|
||||||
{
|
|
||||||
DBG (DBG_WARN, "main: cannot look up `tcp' protocol number");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
level = p->p_proto;
|
|
||||||
}
|
|
||||||
# endif /* SOL_TCP */
|
|
||||||
if (level == -1
|
|
||||||
|| setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on)))
|
|
||||||
DBG (DBG_WARN, "main: failed to put socket in TCP_NODELAY mode (%s)",
|
|
||||||
strerror (errno));
|
|
||||||
#endif /* !TCP_NODELAY */
|
|
||||||
|
|
||||||
DBG (DBG_WARN, "saned from %s ready\n", PACKAGE_STRING);
|
DBG (DBG_WARN, "saned from %s ready\n", PACKAGE_STRING);
|
||||||
|
|
||||||
if (init (&wire) < 0)
|
|
||||||
quit (0);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
reset_watchdog ();
|
|
||||||
process_request (&wire);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SANED_USES_AF_INDEP */
|
#endif /* SANED_USES_AF_INDEP */
|
||||||
|
|
||||||
|
if ((run_mode == SANED_RUN_ALONE) || (run_mode == SANED_RUN_DEBUG))
|
||||||
|
{
|
||||||
|
run_standalone(argc, argv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
run_inetd(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG (DBG_WARN, "saned exiting\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue