/*
- * Copyright (c) 1995-1998, Index Data
+ * Copyright (c) 1995-1999, Index Data
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
* Chas Woodfield, Fretwell Downing Datasystems.
*
* $Log: statserv.c,v $
- * Revision 1.52 1998-08-21 14:13:34 adam
+ * Revision 1.59 1999-11-30 13:47:12 adam
+ * Improved installation. Moved header files to include/yaz.
+ *
+ * Revision 1.58 1999/08/27 09:40:32 adam
+ * Renamed logf function to yaz_log. Removed VC++ project files.
+ *
+ * Revision 1.57 1999/07/06 12:17:15 adam
+ * Added option -1 that runs server once (for profiling purposes).
+ *
+ * Revision 1.56 1999/06/10 11:45:30 adam
+ * Added bend_start, bend_stop handlers and removed pre_init.
+ * Handlers bend_start/bend_stop are called when service/daemon is
+ * started/stopped.
+ *
+ * Revision 1.55 1999/06/10 09:18:54 adam
+ * Modified so that pre_init is called when service/server is started.
+ *
+ * Revision 1.54 1999/04/16 14:45:55 adam
+ * Added interface for tcpd wrapper for access control.
+ *
+ * Revision 1.53 1999/02/02 13:57:39 adam
+ * Uses preprocessor define WIN32 instead of WINDOWS to build code
+ * for Microsoft WIN32.
+ *
+ * Revision 1.52 1998/08/21 14:13:34 adam
* Added GNU Configure script to build Makefiles.
*
* Revision 1.51 1998/07/07 15:51:03 adam
*
*/
-#include <yconfig.h>
#include <stdio.h>
#include <string.h>
-#ifdef WINDOWS
+#ifdef WIN32
#include <process.h>
#include <winsock.h>
#include <direct.h>
#include <signal.h>
#include <errno.h>
-#include <options.h>
-#include <comstack.h>
-#include <tcpip.h>
+#include <yaz/comstack.h>
+#include <yaz/tcpip.h>
+#include <yaz/options.h>
#ifdef USE_XTIMOSI
-#include <xmosi.h>
+#include <yaz/xmosi.h>
#endif
-#include <log.h>
+#include <yaz/log.h>
#include "eventl.h"
#include "session.h"
-#include <statserv.h>
+#include <yaz/statserv.h>
static IOCHAN pListener = NULL;
int check_options(int argc, char **argv);
statserv_options_block control_block = {
1, /* dynamic mode */
+ 0, /* one shot (single session) */
LOG_DEFAULT_LEVEL, /* log level */
"", /* no PDUs */
"", /* diagnostic output to stderr */
1024*1024, /* maximum PDU size (approx.) to allow */
"default-config", /* configuration name to pass to backend */
"", /* set user id */
- NULL, /* pre init handler */
+ 0, /* bend_start handler */
+ 0, /* bend_stop handler */
check_options, /* Default routine, for checking the run-time arguments */
+ check_ip_tcpd,
+ "",
0 /* default value for inet deamon */
-#ifdef WINDOWS
+#ifdef WIN32
,"Z39.50 Server", /* NT Service Name */
"Server", /* NT application Name */
"", /* NT Service Dependencies */
"Z39.50 Server" /* NT Service Display Name */
-#endif /* WINDOWS */
+#endif /* WIN32 */
};
/*
* doing all of the listening and accepting in the parent - it's
* safer that way.
*/
-#ifdef WINDOWS
+#ifdef WIN32
typedef struct _ThreadList ThreadList;
free(pThreadHandles);
}
+ if (control_block.bend_stop)
+ (*control_block.bend_stop)(&control_block);
/* No longer require the critical section, since all threads are dead */
DeleteCriticalSection(&Thread_CritSect);
}
{
if ((res = cs_listen(line, 0, 0)) < 0)
{
- logf(LOG_FATAL, "cs_listen failed");
+ yaz_log(LOG_FATAL, "cs_listen failed");
return;
}
else if (res == 1)
return;
- logf(LOG_DEBUG, "listen ok");
+ yaz_log(LOG_DEBUG, "listen ok");
iochan_setevent(h, EVENT_OUTPUT);
iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
}
if (!(new_line = cs_accept(line)))
{
- logf(LOG_FATAL, "Accept failed.");
+ yaz_log(LOG_FATAL, "Accept failed.");
iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
return;
}
- logf(LOG_DEBUG, "Accept ok");
+ yaz_log(LOG_DEBUG, "Accept ok");
if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
EVENT_INPUT)))
{
- logf(LOG_FATAL, "Failed to create iochan");
+ yaz_log(LOG_FATAL, "Failed to create iochan");
iochan_destroy(h);
return;
}
- logf(LOG_DEBUG, "Creating association");
+ yaz_log(LOG_DEBUG, "Creating association");
if (!(newas = create_association(new_chan, new_line)))
{
- logf(LOG_FATAL, "Failed to create new assoc.");
+ yaz_log(LOG_FATAL, "Failed to create new assoc.");
iochan_destroy(h);
return;
}
- logf(LOG_DEBUG, "Setting timeout %d", control_block.idle_timeout);
+ yaz_log(LOG_DEBUG, "Setting timeout %d", control_block.idle_timeout);
iochan_setdata(new_chan, newas);
iochan_settimeout(new_chan, control_block.idle_timeout * 60);
-#ifndef WINDOWS
- logf(LOG_DEBUG, "Determining client address");
+#ifndef WIN32
+ yaz_log(LOG_DEBUG, "Determining client address");
a = cs_addrstr(new_line);
- logf(LOG_LOG, "Accepted connection from %s", a ? a : "[Unknown]");
+ yaz_log(LOG_LOG, "Accepted connection from %s", a ? a : "[Unknown]");
#endif
/* Now what we need todo is create a new thread with this iochan as
the parameter */
if (NewHandle == (HANDLE)-1)
{
- logf(LOG_FATAL|LOG_ERRNO, "Failed to create new thread.");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create new thread.");
iochan_destroy(h);
return;
}
/* We successfully created the thread, so add it to the list */
statserv_add(NewHandle, new_chan);
- logf(LOG_DEBUG, "Created new thread, iochan %p", new_chan);
+ yaz_log(LOG_DEBUG, "Created new thread, iochan %p", new_chan);
iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
}
else
{
- logf(LOG_FATAL, "Bad event on listener.");
+ yaz_log(LOG_FATAL, "Bad event on listener.");
iochan_destroy(h);
return;
}
}
-#else /* WINDOWS */
+#else /* WIN32 */
/* To save having an #ifdef in event_loop we need to define this empty function */
void statserv_remove(IOCHAN pIOChannel)
iochan_destroy(p);
}
-static int check_ip(void *cd, const char *addr, int len, int type)
-{
- const unsigned char *ip = (const unsigned char *) addr;
- int i;
- char str[64];
-
- sprintf (str, "%u", *ip);
- for (i = 1; i<4; i++)
- sprintf (str + strlen(str), ".%u", ip[i]);
- logf (LOG_DEBUG, "ip %s", str);
- return 0;
-}
-
static void listener(IOCHAN h, int event)
{
COMSTACK line = (COMSTACK) iochan_getdata(h);
if (pipe(hand) < 0)
{
- logf(LOG_FATAL|LOG_ERRNO, "pipe");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "pipe");
iochan_destroy(h);
return;
}
if ((res = fork()) < 0)
{
- logf(LOG_FATAL|LOG_ERRNO, "fork");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "fork");
iochan_destroy(h);
return;
}
if ((res = read(hand[0], dummy, 1)) < 0 && errno != EINTR)
{
- logf(LOG_FATAL|LOG_ERRNO, "handshake read");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "handshake read");
return;
}
else if (res >= 0)
break;
}
- logf(LOG_DEBUG, "P: Child has taken the call");
+ yaz_log(LOG_DEBUG, "P: Child has taken the call");
close(hand[0]);
return;
}
}
- if ((res = cs_listen_check(line, 0, 0, check_ip, 0)) < 0)
+ if ((res = cs_listen_check(line, 0, 0, control_block.check_ip,
+ control_block.daemon_name)) < 0)
{
- logf(LOG_WARN, "cs_listen failed");
+ yaz_log(LOG_WARN, "cs_listen failed");
return;
}
else if (res == 1)
return;
- logf(LOG_DEBUG, "listen ok");
+ yaz_log(LOG_DEBUG, "listen ok");
iochan_setevent(h, EVENT_OUTPUT);
iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
}
if (!(new_line = cs_accept(line)))
{
- logf(LOG_FATAL, "Accept failed.");
+ yaz_log(LOG_FATAL, "Accept failed.");
iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
return;
}
- logf(LOG_DEBUG, "accept ok");
+ yaz_log(LOG_DEBUG, "accept ok");
if (control_block.dynamic)
{
IOCHAN pp;
iochan_destroy(pp);
}
/* release dad */
- logf(LOG_DEBUG, "Releasing parent");
+ yaz_log(LOG_DEBUG, "Releasing parent");
close(hand[1]);
}
else
if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
EVENT_INPUT)))
{
- logf(LOG_FATAL, "Failed to create iochan");
+ yaz_log(LOG_FATAL, "Failed to create iochan");
iochan_destroy(h);
return;
}
pListener = new_chan;
if (!(newas = create_association(new_chan, new_line)))
{
- logf(LOG_FATAL, "Failed to create new assoc.");
+ yaz_log(LOG_FATAL, "Failed to create new assoc.");
iochan_destroy(h);
return;
}
iochan_setdata(new_chan, newas);
iochan_settimeout(new_chan, control_block.idle_timeout * 60);
a = cs_addrstr(new_line);
- logf(LOG_LOG, "Accepted connection from %s", a ? a : "[Unknown]");
+ yaz_log(LOG_LOG, "Accepted connection from %s", a ? a : "[Unknown]");
}
else
{
- logf(LOG_FATAL, "Bad event on listener.");
+ yaz_log(LOG_FATAL, "Bad event on listener.");
iochan_destroy(h);
return;
}
}
-#endif /* WINDOWS */
+#endif /* WIN32 */
static void inetd_connection(int what)
{
iochan_setdata(chan, assoc);
iochan_settimeout(chan, control_block.idle_timeout * 60);
addr = cs_addrstr(line);
- logf(LOG_LOG, "Inetd association from %s", addr ? addr : "[UNKNOWN]");
+ yaz_log(LOG_LOG, "Inetd association from %s", addr ? addr : "[UNKNOWN]");
}
else
{
- logf(LOG_FATAL, "Failed to create association structure");
+ yaz_log(LOG_FATAL, "Failed to create association structure");
}
chan->next = pListener;
pListener = chan;
}
else
{
- logf(LOG_FATAL, "Failed to create iochan");
+ yaz_log(LOG_FATAL, "Failed to create iochan");
}
}
else
{
- logf(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0");
+ yaz_log(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0");
}
}
if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2)
{
- logf (LOG_WARN, "%s: Address format: ('tcp'|'osi')':'<address>", me);
+ yaz_log (LOG_WARN, "%s: Address format: ('tcp'|'osi')':'<address>", me);
return;
}
if (!strcmp(mode, "tcp"))
#ifdef USE_XTIMOSI
type = mosi_type;
#else
- logf (LOG_WARN, "OSI Transport not allowed by configuration.");
+ yaz_log (LOG_WARN, "OSI Transport not allowed by configuration.");
return;
#endif
}
else
{
- logf (LOG_WARN, "You must specify either 'osi:' or 'tcp:'");
+ yaz_log (LOG_WARN, "You must specify either 'osi:' or 'tcp:'");
return;
}
- logf(LOG_LOG, "Adding %s %s listener on %s",
+ yaz_log(LOG_LOG, "Adding %s %s listener on %s",
control_block.dynamic ? "dynamic" : "static",
what == PROTO_SR ? "SR" : "Z3950", where);
if (!(l = cs_create(type, 0, what)))
{
- logf(LOG_FATAL|LOG_ERRNO, "Failed to create listener");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create listener");
return;
}
ap = cs_straddr (l, addr);
}
if (cs_bind(l, ap, CS_SERVER) < 0)
{
- logf(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where);
+ yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where);
cs_close (l);
return;
}
if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
EVENT_EXCEPT)))
{
- logf(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type");
cs_close (l);
return;
}
pListener = lst;
}
-#ifndef WINDOWS
+#ifndef WIN32
/* For windows we don't need to catch the signals */
static void catchchld(int num)
{
;
signal(SIGCHLD, catchchld);
}
-#endif /* WINDOWS */
+#endif /* WIN32 */
statserv_options_block *statserv_getcontrol(void)
{
int ret;
nmem_init ();
-#ifdef WINDOWS
+#ifdef WIN32
/* We need to initialize the thread list */
ThreadList_Initialize();
-#endif /* WINDOWS */
+#endif /* WIN32 */
-#ifdef WINDOWS
+#ifdef WIN32
if ((me = strrchr (argv[0], '\\')))
me++;
else
if (control_block.options_func(argc, argv))
return(1);
-#ifndef WINDOWS
+ if (control_block.bend_start)
+ (*control_block.bend_start)(&control_block);
+#ifndef WIN32
if (control_block.inetd)
inetd_connection(control_block.default_proto);
else
{
- if (control_block.pre_init)
- (*control_block.pre_init)(&control_block);
if (control_block.dynamic)
signal(SIGCHLD, catchchld);
}
if (!(pw = getpwnam(control_block.setuid)))
{
- logf(LOG_FATAL, "%s: Unknown user", control_block.setuid);
+ yaz_log(LOG_FATAL, "%s: Unknown user", control_block.setuid);
return(1);
}
if (setuid(pw->pw_uid) < 0)
{
- logf(LOG_FATAL|LOG_ERRNO, "setuid");
+ yaz_log(LOG_FATAL|LOG_ERRNO, "setuid");
exit(1);
}
}
-#endif /* WINDOWS */
+#endif /* WIN32 */
if ((pListener == NULL) && *control_block.default_listen)
add_listener(control_block.default_listen,
ret = 1;
else
{
- logf(LOG_LOG, "Entering event loop.");
+ yaz_log(LOG_LOG, "Entering event loop.");
ret = event_loop(&pListener);
}
nmem_exit ();
int ret = 0, r;
char *arg;
- while ((ret = options("a:iszSl:v:u:c:w:t:k:", argv, argc, &arg)) != -2)
+ while ((ret = options("1a:iszSl:v:u:c:w:t:k:d:", argv, argc, &arg)) != -2)
{
switch (ret)
{
case 0:
add_listener(arg, control_block.default_proto);
break;
+ case '1':
+ control_block.one_shot = 1;
+ control_block.dynamic = 0;
+ break;
case 'z':
control_block.default_proto = PROTO_Z3950;
break;
case 'c':
strcpy(control_block.configname, arg ? arg : "");
break;
+ case 'd':
+ strcpy(control_block.daemon_name, arg ? arg : "");
+ break;
case 't':
if (!arg || !(r = atoi(arg)))
{
case 'k':
if (!arg || !(r = atoi(arg)))
{
- fprintf(stderr, "%s: Specify positive timeout for -t.\n", me);
+ fprintf(stderr, "%s: Specify positive size for -k.\n", me);
return(1);
}
control_block.maxrecordsize = r * 1024;
default:
fprintf(stderr, "Usage: %s [ -i -a <pdufile> -v <loglevel>"
" -l <logfile> -u <user> -c <config> -t <minutes>"
- " -k <kilobytes>"
+ " -k <kilobytes> -d <daemon>"
" -zsS <listener-addr> -w <directory> ... ]\n", me);
return(1);
}
return 0;
}
-#ifdef WINDOWS
+#ifdef WIN32
typedef struct _Args
{
char **argv;