43#include <libxml/parser.h>
44#include <libxml/tree.h>
45#include <libxml/xinclude.h>
78static char *
me =
"statserver";
81DWORD current_control_tls;
82static int init_control_tls = 0;
83#elif YAZ_POSIX_THREADS
84static pthread_key_t current_control_tls;
85static int init_control_tls = 0;
93#define STAT_DEFAULT_LOG_LEVEL "server,session,request"
139 const char *details = 0;
148 yaz_log(level,
"%s: cs=%d msg=%s details=%s",
149 message, code,
cs_errmsg(code), details);
151 yaz_log(level,
"%s: cs=%d msg=%s",
181 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
182 strcmp((
const char *) ptr->name,
"yazgfs"))
202 for (p = ptr; p; p = p->next)
204 if (p->type == XML_TEXT_NODE)
205 len += xmlStrlen(p->content);
210 for (p = ptr; p; p = p->next)
212 if (p->type == XML_TEXT_NODE)
222 strcat((
char *)str, (
const char *)cp);
226 cp = strlen((
const char *)str) + str;
290 char vhost[128], *cp;
293 strncpy(vhost, host, 127);
295 cp = strchr(vhost,
':');
306 int listen_match = 0;
319 if (listen_match && host_match)
372 for (ptr = ptr->children; ptr; ptr = ptr->next)
374 struct _xmlAttr *attr;
375 if (ptr->type != XML_ELEMENT_NODE)
377 attr = ptr->properties;
378 if (!strcmp((
const char *) ptr->name,
"listen"))
384 const char *address =
386 for ( ; attr; attr = attr->next)
387 if (!xmlStrcmp(attr->name, BAD_CAST
"id")
388 && attr->children && attr->children->type == XML_TEXT_NODE)
393 gfslp = &(*gfslp)->
next;
397 else if (!strcmp((
const char *) ptr->name,
"server"))
399 xmlNodePtr ptr_server = ptr;
401 const char *listenref = 0;
405 for ( ; attr; attr = attr->next)
406 if (!xmlStrcmp(attr->name, BAD_CAST
"listenref")
407 && attr->children && attr->children->type == XML_TEXT_NODE)
409 else if (!xmlStrcmp(attr->name, BAD_CAST
"id")
411 && attr->children->type == XML_TEXT_NODE)
424 sizeof(
int) * (num + 1));
425 for (i = 0; i < num; i++)
430 for (id_no = 1; gl; gl = gl->
next, id_no++)
431 if (gl->
id && !strcmp(gl->
id, refs[i]))
438 "in server config element", refs[i]);
442 for (ptr = ptr_server->children; ptr; ptr = ptr->next)
444 if (ptr->type != XML_ELEMENT_NODE)
446 if (!strcmp((
const char *) ptr->name,
"host"))
451 else if (!strcmp((
const char *) ptr->name,
"config"))
458 base_path, 0, fpath))
461 else if (!strcmp((
const char *) ptr->name,
"cql2rpn"))
472 "open CQL transform file '%s'", fname);
476 else if (!strcmp((
const char *) ptr->name,
"ccl2rpn"))
478 char *fname, fpath[1024];
485 if ((f = fopen(fname,
"r")) == 0) {
493 else if (!strcmp((
const char *) ptr->name,
"directory"))
498 else if (!strcmp((
const char *) ptr->name,
"docpath"))
503 else if (!strcmp((
const char *) ptr->name,
"maximumrecordsize"))
508 else if (!strcmp((
const char *) ptr->name,
"stylesheet"))
513 else if (!strcmp((
const char *) ptr->name,
514 "client_query_charset"))
519 else if (!strcmp((
const char *) ptr->name,
"explain"))
523 else if (!strcmp((
const char *) ptr->name,
"retrievalinfo"))
542 gfsp = &(*gfsp)->
next;
559 init_control_tls = 1;
560 current_control_tls = TlsAlloc();
561#elif YAZ_POSIX_THREADS
562 init_control_tls = 1;
563 pthread_key_create(¤t_control_tls, 0);
568 if (fname[0] ==
'\0')
582 if (noSubstitutions == -1)
590 last_p = strrchr(fname,
622 if (init_control_tls)
623 TlsFree(current_control_tls);
624#elif YAZ_POSIX_THREADS
625 if (init_control_tls)
626 pthread_key_delete(current_control_tls);
636 for (id_no = 1; gfs; gfs = gfs->
next, id_no++)
649 for (; gfs; gfs = gfs->
next)
675 for (; gfs; gfs = gfs->
next)
703typedef struct _ThreadList ThreadList;
712static ThreadList *pFirstThread;
713static CRITICAL_SECTION Thread_CritSect;
714static BOOL bInitialized = FALSE;
716static void ThreadList_Initialize()
719 InitializeCriticalSection(&Thread_CritSect);
728static void statserv_add(HANDLE hThread,
IOCHAN pIOChannel)
731 EnterCriticalSection(&Thread_CritSect);
735 ThreadList *pNewThread = (ThreadList *)
malloc(
sizeof(ThreadList));
736 pNewThread->hThread = hThread;
737 pNewThread->pIOChannel = pIOChannel;
738 pNewThread->pNext = pFirstThread;
739 pFirstThread = pNewThread;
742 LeaveCriticalSection(&Thread_CritSect);
749 EnterCriticalSection(&Thread_CritSect);
752 ThreadList *pCurrentThread = pFirstThread;
753 ThreadList *pNextThread;
754 ThreadList *pPrevThread =NULL;
757 for (; pCurrentThread != NULL; pCurrentThread = pNextThread)
760 if (pCurrentThread->pIOChannel == pIOChannel)
764 if (pPrevThread == NULL)
765 pFirstThread = pCurrentThread->pNext;
767 pPrevThread->pNext = pCurrentThread->pNext;
770 free(pCurrentThread);
778 pNextThread = pCurrentThread->pNext;
779 pPrevThread = pCurrentThread;
784 LeaveCriticalSection(&Thread_CritSect);
795 HANDLE *pThreadHandles = NULL;
799 EnterCriticalSection(&Thread_CritSect);
804 ThreadList *pCurrentThread = pFirstThread;
810 for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext)
814 closesocket(pCurrentThread->pIOChannel->fd);
822 HANDLE *pCurrentHandle ;
825 pThreadHandles = (HANDLE *)
malloc(
sizeof(HANDLE) * iHandles);
826 pCurrentHandle = pThreadHandles;
828 for (pCurrentThread = pFirstThread;
829 pCurrentThread != NULL;
830 pCurrentThread = pCurrentThread->pNext, pCurrentHandle++)
833 *pCurrentHandle = pCurrentThread->hThread;
838 LeaveCriticalSection(&Thread_CritSect);
846 WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE);
849 free(pThreadHandles);
854 DeleteCriticalSection(&Thread_CritSect);
921 newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);
922 if (newHandle == (HANDLE) -1)
930 statserv_add(newHandle, new_chan);
932 yaz_log(
YLOG_DEBUG,
"Created new thread, id = %ld iochan %p",(
long) newHandle, new_chan);
1004 if ((res = fork()) < 0)
1036#if YAZ_POSIX_THREADS
1037 pthread_t child_thread;
1038 pthread_create(&child_thread, 0,
new_session, new_line);
1039 pthread_detach(child_thread);
1067 unsigned cs_get_mask, cs_accept_mask, mask =
1073 cs_accept_mask = mask;
1106 no_sessions, a ? a :
"[Unknown]", (
long) getpid());
1143 addr ? addr :
"[UNKNOWN]");
1182 listen_id, (
long) getpid());
1222 for (; l; l = l->
next)
1230 while (waitpid(-1, 0, WNOHANG) > 0)
1239 if (init_control_tls)
1243#elif YAZ_POSIX_THREADS
1244 if (init_control_tls)
1246 pthread_getspecific(current_control_tls);
1264 if (init_control_tls)
1265 TlsSetValue(current_control_tls, block);
1266#elif YAZ_POSIX_THREADS
1267 if (init_control_tls)
1268 pthread_setspecific(current_control_tls, block);
1295 char vstr[20], sha1_str[41];
1300 printf(
"YAZ DLL/SO: %s %s\n", vstr, sha1_str);
1309 ThreadList_Initialize();
1319 if ((
me = strrchr(argv[0], sep)))
1389 while ((ret =
options(
"1a:iszSTl:v:u:c:w:t:k:Kd:A:p:DC:f:m:r:V",
1390 argv, argc, &arg)) != -2)
1406 fprintf(stderr,
"%s: SR protocol no longer supported\n",
me);
1413#if YAZ_POSIX_THREADS
1417 fprintf(stderr,
"%s: Threaded mode not available.\n",
me);
1427 fprintf(stderr,
"%s: Specify time format for log file.\n",
me);
1452 if (!arg || !(r = atoi(arg)))
1454 fprintf(stderr,
"%s: Specify positive timeout for -t.\n",
me);
1460 if (!arg || !(r = atoi(arg)))
1462 fprintf(stderr,
"%s: Specify positive size for -k.\n",
me);
1490 fprintf(stderr,
"%s: Option -f unsupported since YAZ is compiled without Libxml2 support\n",
me);
1498 if (!arg || !(r = atoi(arg)))
1500 fprintf(stderr,
"%s: Specify positive size for -r.\n",
me);
1509 fprintf(stderr,
"Usage: %s [ -a <pdufile> -v <loglevel>"
1510 " -l <logfile> -u <user> -c <config> -t <minutes>"
1511 " -k <kilobytes> -d <daemon> -p <pidfile> -C certfile"
1512 " -zKiDSTV1 -m <time-format> -w <directory> <listener-addr>... ]\n",
me);
1535 cb->service_name, cb->service_display_name
void ccl_qual_file(CCL_bibset bibset, FILE *inf)
CCL_bibset ccl_qual_mk(void)
creates Bibset
int cs_get_error(COMSTACK cs, const char **details)
Returns the last COMSTACK error and optional transport details.
void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
Sets the maximum incoming message size.
const char * cs_errmsg(int n)
Returns a static message for a COMSTACK error code.
COMSTACK cs_create_host(const char *vhost, int flags, void **vp)
Creates an endpoint from a host or URI specification.
Transport-independent communication endpoints for BER and HTTP.
#define cs_bind(handle, ad, mo)
Binds an endpoint to a local address.
#define cs_addrstr(handle)
Formats the peer address as text.
#define cs_close(handle)
Closes the socket and frees the endpoint and its transport state.
#define cs_accept(handle)
Creates an endpoint for a connection received by cs_listen.
#define cs_errno(handle)
Returns the last COMSTACK error code.
#define cs_createbysocket(sock, type, flags, proto)
Creates an endpoint around an existing socket.
#define cs_fileno(handle)
Returns the socket descriptor, or -1 if none has been created.
struct comstack * COMSTACK
Communication endpoint; release with cs_close.
#define cs_listen(handle, ap, al)
Receives an incoming connection for subsequent cs_accept.
#define CS_FLAGS_NUMERICHOST
#define cs_listen_check(handle, ap, al, cf, cd)
Receives an incoming connection with an optional access check.
int yaz_daemon(const char *progname, unsigned int flags, void(*work)(void *data), void *data, const char *pidfile, const char *uid)
daemon utility.
Header for errno utilities.
int iochan_event_loop(IOCHAN *iochans, int *watch_sig)
IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags, int chan_id)
Definitions for event loop handling for GFS.
#define iochan_settimeout(i, t)
#define iochan_getdata(i)
#define iochan_destroy(i)
#define iochan_getnext(i)
#define iochan_setdata(i, d)
void statserv_remove(IOCHAN pIOChannel)
#define iochan_setflags(i, d)
void yaz_log_init_prefix(const char *prefix)
sets log message prefix
int yaz_log_mask_str(const char *str)
converts log level string to log level (integer)
void yaz_log_init_max_size(int mx)
sets limit in bytes for size for log file
void yaz_log_init_level(int level)
sets log level
void yaz_log_time_format(const char *fmt)
sets time format for log mesages
void yaz_log(int level, const char *fmt,...)
Writes log message.
void yaz_log_init_file(const char *fname)
sets log file
int yaz_log_module_level(const char *name)
returns level for module
#define YLOG_WARN
log level: warning
#define YLOG_FATAL
log level: fatal
#define YLOG_ERRNO
log level: append system error message
#define YLOG_DEBUG
log level: debugging
#define YLOG_LOG
log level: log (regular)
NMEM nmem_create(void)
returns new NMEM handle
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
struct nmem_control * NMEM
NMEM handle (an opaque pointer to memory).
void nmem_strsplit(NMEM nmem, const char *delim, const char *dstr, char ***darray, int *num)
allocates sub strings out of string using certain delimitors
char * nmem_printf(NMEM nmem, const char *fmt,...)
formats and prints a string into NMEM allocated memory
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
char * nmem_strdup_null(NMEM mem, const char *src)
allocates string on NMEM handle - allows NULL ptr buffer
int options(const char *desc, char **argv, int argc, char **arg)
command-line options parsing for main
Header for command line options parsing utilities.
const char * yaz_retrieval_get_error(yaz_retrieval_t p)
int yaz_retrieval_configure(yaz_retrieval_t p, const xmlNode *ptr)
yaz_retrieval_t yaz_retrieval_create()
void yaz_retrieval_set_path(yaz_retrieval_t p, const char *path)
void yaz_sc_destroy(yaz_sc_t *s)
frees service control handle
int yaz_sc_program(yaz_sc_t s, int argc, char **argv, int(*sc_main)(yaz_sc_t s, int argc, char **argv), void(*sc_stop)(yaz_sc_t s))
registers service controlled program
yaz_sc_t yaz_sc_create(const char *service_name, const char *display_name)
creates service handle
void yaz_sc_running(yaz_sc_t s)
signals that sc_main applicatio starts running
Header for Windows Service Control utility.
association * create_association(IOCHAN channel, COMSTACK link, const char *apdufile)
static void get_logbits(void)
void ir_session(IOCHAN h, int event)
static int log_sessiondetail
int control_association(association *assoc, const char *host, int force)
void yaz_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Header for config file reading utilities.
static void * new_session(void *vp)
static void option_copy(char *dst, const char *src)
static xmlDocPtr xml_config_doc
static void log_comstack_error(int level, COMSTACK cs, const char *fmt,...)
int statserv_main(int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), void(*bend_close)(void *handle))
static struct gfs_listen * gfs_listen_list
static int statserv_sc_main(yaz_sc_t s, int argc, char **argv)
static struct gfs_server * gfs_server_new(const char *id)
static void gfs_server_chdir(struct gfs_server *gfs)
static char gfs_root_dir[FILENAME_MAX+1]
static char * nmem_dup_xml_content(NMEM n, xmlNodePtr ptr)
static void statserv_reset(void)
static char * programname
static void catchchld(int num)
static void remove_listeners(void)
static struct gfs_server * gfs_server_list
static void inetd_connection(int what)
static void listener(IOCHAN h, int event)
static void xml_config_close(void)
int check_options(int argc, char **argv)
void statserv_sc_stop(yaz_sc_t s)
static statserv_options_block * current_control_block
statserv_options_block control_block
#define STAT_DEFAULT_LOG_LEVEL
void statserv_setcontrol(statserv_options_block *block)
static int xml_config_add_listeners(void)
statserv_options_block * statserv_getcontrol(void)
static void xml_config_read(const char *base_path)
static void xml_config_bend_start(void)
static struct gfs_listen * gfs_listen_new(const char *id, const char *address)
static void statserv_closedown(void)
static void normal_stop_handler(int num)
static int add_listener(char *where, int listen_id)
static void daemon_handler(void *data)
static xmlNodePtr xml_config_get_root(void)
static void show_version(void)
static void xml_config_bend_stop(void)
static int xml_config_open(void)
Header for GFS (Obsolete. Use yaz/backend.h).
struct bend_initrequest * init
struct gfs_server * server
statserv_options_block * last_control
Information for the Init handler.
result for init handler (must be filled by handler)
yaz_retrieval_t retrieval
cql_transform_t cql_transform
statserv_options_block cb
char * client_query_charset
char daemon_name[BEND_NAME_MAX]
char apdufile[BEND_NAME_MAX]
void(*) bend_stop(struct statserv_options_block *p)
int(*) options_func(int argc, char **argv)
char cert_fname[BEND_NAME_MAX]
bend_initresult *(*) bend_init(bend_initrequest *r)
char pid_fname[BEND_NAME_MAX]
enum oid_proto default_proto
void(*) bend_close(void *handle)
char xml_config[BEND_NAME_MAX]
int(*) check_ip(void *cd, const char *addr, int len, int type)
char setuid[BEND_NAME_MAX]
char logfile[BEND_NAME_MAX]
char configname[BEND_NAME_MAX]
void(*) bend_start(struct statserv_options_block *p)
int check_ip_tcpd(void *cd, const char *addr, int len, int type)
int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
Selects certificate and private key files for a TLS endpoint.
COMSTACK tcpip_type(int s, int flags, int protocol, void *vp)
Header for TCP/IP + SSL COMSTACK.
char * yaz_filepath_resolve(const char *fname, const char *path, const char *base, char *fullpath)
resolve file on path
unsigned long yaz_version(char *version_str, char *sha1_str)
returns YAZ version
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
WRBUF wrbuf_alloc(void)
construct WRBUF
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
#define xfree(x)
utility macro which calls xfree_f
void yaz_log_xml_errors(const char *prefix, int log_level)
Makes Libxml2 and Libxslt log errors through yaz_log.
Header for YAZ iconv interface.
#define YAZ_VERSION
YAZ version as string.
#define YAZ_VERSION_SHA1
SHA1 ID for YAZ (Git).
void bend_close(void *handle)
bend_initresult * bend_init(bend_initrequest *q)