From: Adam Dickmeiss Date: Mon, 1 Sep 1997 08:52:58 +0000 (+0000) Subject: New windows NT/95 port using MSV5.0. The test server 'ztest' was X-Git-Tag: YAZ.1.8~630 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=69e1deffc8ce5541d72110417f9e555f7e33aac2 New windows NT/95 port using MSV5.0. The test server 'ztest' was moved a separate directory. MSV5.0 project server.dsp created. As an option, the server can now operate as an NT service. --- diff --git a/server/Makefile b/server/Makefile index abdb1e0..c222307 100644 --- a/server/Makefile +++ b/server/Makefile @@ -1,7 +1,7 @@ -# Copyright (C) 1994, Index Data I/S +# Copyright (C) 1994-1997, Index Data I/S # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile,v 1.31 1996-10-08 10:45:05 quinn Exp $ +# $Id: Makefile,v 1.32 1997-09-01 08:52:58 adam Exp $ LIBDIR=../lib @@ -16,16 +16,9 @@ LIBS=$(LIBDIR)/libserver.a $(LIBDIR)/libasn.a $(LIBDIR)/libodr.a \ $(LIBDIR)/libcomstack.a $(LIBMOSI) $(LIBDIR)/libutil.a $(ELIBS) PO = eventl.o seshigh.o statserv.o requestq.o CPP=$(CC) -E -PROG=ztest -PROGO=ztest.o read-grs.o RANLIB=ranlib -all: $(LIBDIR) $(LIB) $(PROG) - -$(PROG): $(LIB) $(PROGO) - $(CC) $(CFLAGS) $(LIBINCLUDE) -o $(PROG) $(PROGO) $(LIBS) - -alll: +all: $(LIBDIR) $(LIB) $(LIB): $(PO) rm -f $(LIB) diff --git a/server/eventl.c b/server/eventl.c index cd5aa48..c4120fb 100644 --- a/server/eventl.c +++ b/server/eventl.c @@ -4,7 +4,12 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: eventl.c,v $ - * Revision 1.22 1996-07-06 19:58:35 quinn + * Revision 1.23 1997-09-01 08:52:59 adam + * New windows NT/95 port using MSV5.0. The test server 'ztest' was + * moved a separate directory. MSV5.0 project server.dsp created. + * As an option, the server can now operate as an NT service. + * + * Revision 1.22 1996/07/06 19:58:35 quinn * System headerfiles gathered in yconfig * * Revision 1.21 1996/02/21 12:55:51 quinn @@ -76,15 +81,24 @@ #include #include #include +#ifdef WINDOWS +#include +#else #include +#endif #include #include #include -#include - +#include "eventl.h" +#include "log.h" +#include "comstack.h" +#include "session.h" +#include "statserv.h" #include +#ifndef WINDOWS + static IOCHAN iochans = 0; IOCHAN iochan_getchan(void) @@ -92,113 +106,140 @@ IOCHAN iochan_getchan(void) return iochans; } +#endif /* WINDOWS */ + IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags) { - IOCHAN new; + IOCHAN new_iochan; - if (!(new = xmalloc(sizeof(*new)))) + if (!(new_iochan = xmalloc(sizeof(*new_iochan)))) return 0; - new->destroyed = 0; - new->fd = fd; - new->flags = flags; - new->fun = cb; - new->next = iochans; - new->force_event = 0; - new->last_event = new->max_idle = 0; - iochans = new; - return new; + new_iochan->destroyed = 0; + new_iochan->fd = fd; + new_iochan->flags = flags; + new_iochan->fun = cb; + new_iochan->force_event = 0; + new_iochan->last_event = new_iochan->max_idle = 0; + +#ifdef WINDOWS + /* For windows we don't have a linklist of iochans */ + new_iochan->next = NULL; +#else /* WINDOWS */ + new_iochan->next = iochans; + iochans = new_iochan; +#endif /* WINDOWS */ + + return new_iochan; } -int event_loop() +/* Event loop now takes an iochan as a parameter */ +#ifdef WINDOWS +int __stdcall event_loop(IOCHAN iochans) +#else +int event_loop(IOCHAN dummylistener) +#endif { do /* loop as long as there are active associations to process */ { IOCHAN p, nextp; - fd_set in, out, except; - int res, max; - static struct timeval nullto = {0, 0}, to; - struct timeval *timeout; - - FD_ZERO(&in); - FD_ZERO(&out); - FD_ZERO(&except); - timeout = &to; /* hang on select */ - to.tv_sec = 5*60; - to.tv_usec = 0; - max = 0; - for (p = iochans; p; p = p->next) - { - if (p->force_event) - timeout = &nullto; /* polling select */ - if (p->flags & EVENT_INPUT) - FD_SET(p->fd, &in); - if (p->flags & EVENT_OUTPUT) - FD_SET(p->fd, &out); - if (p->flags & EVENT_EXCEPT) - FD_SET(p->fd, &except); - if (p->fd > max) - max = p->fd; - } - if ((res = select(max + 1, &in, &out, &except, timeout)) < 0) - { - if (errno == EINTR) - continue; - return 1; - } + fd_set in, out, except; + int res, max; + static struct timeval nullto = {0, 0}, to; + struct timeval *timeout; + + FD_ZERO(&in); + FD_ZERO(&out); + FD_ZERO(&except); + timeout = &to; /* hang on select */ + to.tv_sec = 5*60; + to.tv_usec = 0; + max = 0; for (p = iochans; p; p = p->next) { - int force_event = p->force_event; - time_t now = time(0); - - p->force_event = 0; - if (!p->destroyed && (FD_ISSET(p->fd, &in) || force_event == - EVENT_INPUT)) - { - p->last_event = now; - (*p->fun)(p, EVENT_INPUT); + if (p->force_event) + timeout = &nullto; /* polling select */ + if (p->flags & EVENT_INPUT) + FD_SET(p->fd, &in); + if (p->flags & EVENT_OUTPUT) + FD_SET(p->fd, &out); + if (p->flags & EVENT_EXCEPT) + FD_SET(p->fd, &except); + if (p->fd > max) + max = p->fd; } - if (!p->destroyed && (FD_ISSET(p->fd, &out) || - force_event == EVENT_OUTPUT)) + if ((res = select(max + 1, &in, &out, &except, timeout)) < 0) { - p->last_event = now; - (*p->fun)(p, EVENT_OUTPUT); + if (errno == EINTR) + continue; + else + { + /* Destroy the first member in the chain, and try again */ + association *assoc = iochan_getdata(iochans); + COMSTACK conn = assoc->client_link; + + cs_close(conn); + destroy_association(assoc); + iochan_destroy(iochans); + logf(LOG_DEBUG, "error while selecting, destroying iochan %p", iochans); + } } - if (!p->destroyed && (FD_ISSET(p->fd, &except) || - force_event == EVENT_EXCEPT)) - { - p->last_event = now; - (*p->fun)(p, EVENT_EXCEPT); + for (p = iochans; p; p = p->next) + { + int force_event = p->force_event; + time_t now = time(0); + + p->force_event = 0; + if (!p->destroyed && (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_INPUT); + } + if (!p->destroyed && (FD_ISSET(p->fd, &out) || + force_event == EVENT_OUTPUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_OUTPUT); + } + if (!p->destroyed && (FD_ISSET(p->fd, &except) || + force_event == EVENT_EXCEPT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_EXCEPT); + } + if (!p->destroyed && ((p->max_idle && now - p->last_event > + p->max_idle) || force_event == EVENT_TIMEOUT)) + { + p->last_event = now; + (*p->fun)(p, EVENT_TIMEOUT); + } } - if (!p->destroyed && ((p->max_idle && now - p->last_event > - p->max_idle) || force_event == EVENT_TIMEOUT)) + for (p = iochans; p; p = nextp) { - p->last_event = now; - (*p->fun)(p, EVENT_TIMEOUT); - } - } - for (p = iochans; p; p = nextp) - { - nextp = p->next; + nextp = p->next; - if (p->destroyed) - { - IOCHAN tmp = p, pr; - - if (p == iochans) - iochans = p->next; - else - { - for (pr = iochans; pr; pr = pr->next) - if (pr->next == p) - break; - assert(pr); /* grave error if it weren't there */ - pr->next = p->next; - } - if (nextp == p) - nextp = p->next; - xfree(tmp); + if (p->destroyed) + { + IOCHAN tmp = p, pr; + + /* We need to inform the threadlist that this channel has been destroyed */ + statserv_remove(p); + + /* Now reset the pointers */ + if (p == iochans) + iochans = p->next; + else + { + for (pr = iochans; pr; pr = pr->next) + if (pr->next == p) + break; + assert(pr); /* grave error if it weren't there */ + pr->next = p->next; + } + if (nextp == p) + nextp = p->next; + xfree(tmp); + } } - } } while (iochans); return 0; diff --git a/server/requestq.c b/server/requestq.c index d9a3a34..80fe7e8 100644 --- a/server/requestq.c +++ b/server/requestq.c @@ -4,7 +4,12 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: requestq.c,v $ - * Revision 1.2 1995-11-01 13:54:57 quinn + * Revision 1.3 1997-09-01 08:53:00 adam + * New windows NT/95 port using MSV5.0. The test server 'ztest' was + * moved a separate directory. MSV5.0 project server.dsp created. + * As an option, the server can now operate as an NT service. + * + * Revision 1.2 1995/11/01 13:54:57 quinn * Minor adjustments * * Revision 1.1 1995/05/15 12:12:22 quinn @@ -23,9 +28,7 @@ #include #include -#include - -static request *request_list = 0; /* global freelist for requests */ +#include "session.h" void request_enq(request_q *q, request *r) { @@ -57,16 +60,27 @@ request *request_deq(request_q *q) void request_initq(request_q *q) { - q->head = q->tail = 0; + q->head = q->tail = q->list = 0; q->num = 0; } -request *request_get(void) +void request_delq(request_q *q) +{ + request *r1, *r = q->list; + while (r) + { + r1 = r; + r = r->next; + xfree (r1); + } +} + +request *request_get(request_q *q) { - request *r = request_list; + request *r = q->list; if (r) - request_list = r->next; + q->list = r->next; else { if (!(r = xmalloc(sizeof(*r)))) @@ -74,6 +88,7 @@ request *request_get(void) r->response = 0; r->size_response = 0; } + r->q = q; r->len_refid = 0; r->request = 0; r->request_mem = 0; @@ -85,6 +100,7 @@ request *request_get(void) void request_release(request *r) { - r->next = request_list; - request_list = r; + request_q *q = r->q; + r->next = q->list; + q->list = r; } diff --git a/server/server.dsp b/server/server.dsp new file mode 100644 index 0000000..66295acb2 --- /dev/null +++ b/server/server.dsp @@ -0,0 +1,116 @@ +# Microsoft Developer Studio Project File - Name="server" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=server - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "server.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "server.mak" CFG="server - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "server - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "server - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "server - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "WINDOWS" /FD /c +# SUBTRACT CPP /YX +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +OutDir=.\Release +ProjDir=. +TargetName=server +SOURCE=$(InputPath) +PostBuild_Desc=Copy lib +PostBuild_Cmds=copy $(OutDir)\$(TargetName).lib $(ProjDir)\..\lib +# End Special Build Tool + +!ELSEIF "$(CFG)" == "server - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "WINDOWS" /FR /FD /c +# SUBTRACT CPP /YX +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# Begin Special Build Tool +OutDir=.\Debug +ProjDir=. +TargetName=server +SOURCE=$(InputPath) +PostBuild_Desc=Copy lib +PostBuild_Cmds=copy $(OutDir)\$(TargetName).lib $(ProjDir)\..\lib +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "server - Win32 Release" +# Name "server - Win32 Debug" +# Begin Source File + +SOURCE=.\eventl.c +# End Source File +# Begin Source File + +SOURCE=.\requestq.c +# End Source File +# Begin Source File + +SOURCE=.\seshigh.c +# End Source File +# Begin Source File + +SOURCE=.\session.h +# End Source File +# Begin Source File + +SOURCE=.\statserv.c +# End Source File +# End Target +# End Project diff --git a/server/seshigh.c b/server/seshigh.c index 586af65..94c4d45 100644 --- a/server/seshigh.c +++ b/server/seshigh.c @@ -4,7 +4,12 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: seshigh.c,v $ - * Revision 1.64 1997-04-30 08:52:11 quinn + * Revision 1.65 1997-09-01 08:53:01 adam + * New windows NT/95 port using MSV5.0. The test server 'ztest' was + * moved a separate directory. MSV5.0 project server.dsp created. + * As an option, the server can now operate as an NT service. + * + * Revision 1.64 1997/04/30 08:52:11 quinn * Null * * Revision 1.63 1996/10/11 11:57:26 quinn @@ -229,13 +234,17 @@ #include #include #include +#ifdef WINDOWS +#include +#else #include +#endif #include #include #include -#include -#include +#include "eventl.h" +#include "session.h" #include #include #include @@ -342,14 +351,16 @@ void destroy_association(association *h) bend_close(h->backend); while (request_deq(&h->incoming)); while (request_deq(&h->outgoing)); - xfree(h); + request_delq(&h->incoming); + request_delq(&h->outgoing); + xfree(h); } static void do_close(association *a, int reason, char *message) { Z_APDU apdu; Z_Close *cls = zget_Close(a->encode); - request *req = request_get(); + request *req = request_get(&a->outgoing); /* Purge request queue */ while (request_deq(&a->incoming)); @@ -437,13 +448,13 @@ void ir_session(IOCHAN h, int event) /* we got a complete PDU. Let's decode it */ logf(LOG_DEBUG, "Got PDU, %d bytes", res); - req = request_get(); /* get a new request structure */ + req = request_get(&assoc->incoming); /* get a new request structure */ odr_reset(assoc->decode); odr_setbuf(assoc->decode, assoc->input_buffer, res, 0); if (!z_APDU(assoc->decode, &req->request, 0)) { logf(LOG_LOG, "ODR error on incoming PDU: %s [near byte %d] ", - odr_errlist[odr_geterror(assoc->decode)], + odr_errmsg(odr_geterror(assoc->decode)), odr_offset(assoc->decode)); logf(LOG_LOG, "PDU dump:"); odr_dumpBER(log_file(), assoc->input_buffer, res); @@ -454,7 +465,7 @@ void ir_session(IOCHAN h, int event) if (assoc->print && !z_APDU(assoc->print, &req->request, 0)) { logf(LOG_WARN, "ODR print error: %s", - odr_errlist[odr_geterror(assoc->print)]); + odr_errmsg(odr_geterror(assoc->print))); odr_reset(assoc->print); } request_enq(&assoc->incoming, req); @@ -602,7 +613,7 @@ static int process_response(association *assoc, request *req, Z_APDU *res) if (!z_APDU(assoc->encode, &res, 0)) { logf(LOG_WARN, "ODR error when encoding response: %s", - odr_errlist[odr_geterror(assoc->decode)]); + odr_errmsg(odr_geterror(assoc->decode))); odr_reset(assoc->encode); return -1; } @@ -613,7 +624,7 @@ static int process_response(association *assoc, request *req, Z_APDU *res) if (assoc->print && !z_APDU(assoc->print, &res, 0)) { logf(LOG_WARN, "ODR print error: %s", - odr_errlist[odr_geterror(assoc->print)]); + odr_errmsg(odr_geterror(assoc->print))); odr_reset(assoc->print); } /* change this when we make the backend reentrant */ @@ -743,131 +754,111 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) /* * nonsurrogate diagnostic record. */ -static Z_Records *diagrec(oid_proto proto, int error, char *addinfo) +static Z_Records *diagrec(association *assoc, int error, char *addinfo) { - static Z_Records rec; + Z_Records *rec = odr_malloc (assoc->encode, sizeof(*rec)); oident bib1; - static int err; -#ifdef Z_95 - static Z_DiagRec drec; - static Z_DefaultDiagFormat dr; -#else - static Z_DiagRec dr; -#endif + int *err = odr_malloc (assoc->encode, sizeof(*err)); + Z_DiagRec *drec = odr_malloc (assoc->encode, sizeof(*drec)); + Z_DefaultDiagFormat *dr = odr_malloc (assoc->encode, sizeof(*dr)); - bib1.proto = proto; + bib1.proto = assoc->proto; bib1.oclass = CLASS_DIAGSET; bib1.value = VAL_BIB1; logf(LOG_DEBUG, "Diagnostic: %d -- %s", error, addinfo ? addinfo : "NULL"); - err = error; - rec.which = Z_Records_NSD; + *err = error; + rec->which = Z_Records_NSD; #ifdef Z_95 - rec.u.nonSurrogateDiagnostic = &drec; - drec.which = Z_DiagRec_defaultFormat; - drec.u.defaultFormat = &dr; + rec->u.nonSurrogateDiagnostic = drec; + drec->which = Z_DiagRec_defaultFormat; + drec->u.defaultFormat = dr; #else - rec.u.nonSurrogateDiagnostic = &dr; + rec->u.nonSurrogateDiagnostic = dr; #endif - dr.diagnosticSetId = oid_getoidbyent(&bib1); - dr.condition = &err; - dr.which = Z_DiagForm_v2AddInfo; - dr.addinfo = addinfo ? addinfo : ""; - return &rec; + dr->diagnosticSetId = oid_getoidbyent(&bib1); + dr->condition = err; + dr->which = Z_DiagForm_v2AddInfo; + dr->addinfo = addinfo ? addinfo : ""; + return rec; } /* * surrogate diagnostic. */ -static Z_NamePlusRecord *surrogatediagrec(oid_proto proto, char *dbname, +static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname, int error, char *addinfo) { - static Z_NamePlusRecord rec; - static int err; + Z_NamePlusRecord *rec = odr_malloc (assoc->encode, sizeof(*rec)); + int *err = odr_malloc (assoc->encode, sizeof(*err)); oident bib1; -#ifdef Z_95 - static Z_DiagRec drec; - static Z_DefaultDiagFormat dr; -#else - static Z_DiagRec dr; -#endif + Z_DiagRec *drec = odr_malloc (assoc->encode, sizeof(*drec)); + Z_DefaultDiagFormat *dr = odr_malloc (assoc->encode, sizeof(*dr)); - bib1.proto = proto; + bib1.proto = assoc->proto; bib1.oclass = CLASS_DIAGSET; bib1.value = VAL_BIB1; logf(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo); - err = error; - rec.databaseName = dbname; - rec.which = Z_NamePlusRecord_surrogateDiagnostic; -#ifdef Z_95 - rec.u.surrogateDiagnostic = &drec; - drec.which = Z_DiagRec_defaultFormat; - drec.u.defaultFormat = &dr; -#else - rec.u.surrogateDiagnostic = &dr; -#endif - dr.diagnosticSetId = oid_getoidbyent(&bib1); - dr.condition = &err; - dr.which = Z_DiagForm_v2AddInfo; - dr.addinfo = addinfo ? addinfo : ""; - return &rec; + *err = error; + rec->databaseName = dbname; + rec->which = Z_NamePlusRecord_surrogateDiagnostic; + rec->u.surrogateDiagnostic = drec; + drec->which = Z_DiagRec_defaultFormat; + drec->u.defaultFormat = dr; + dr->diagnosticSetId = oid_getoidbyent(&bib1); + dr->condition = err; + dr->which = Z_DiagForm_v2AddInfo; + dr->addinfo = addinfo ? addinfo : ""; + return rec; } /* * multiple nonsurrogate diagnostics. */ -static Z_DiagRecs *diagrecs(oid_proto proto, int error, char *addinfo) +static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo) { - static Z_DiagRecs recs; - static int err; + Z_DiagRecs *recs = odr_malloc (assoc->encode, sizeof(*recs)); + int *err = odr_malloc (assoc->encode, sizeof(*err)); oident bib1; -#ifdef Z_95 - static Z_DiagRec *recp[1], drec; - static Z_DefaultDiagFormat rec; -#else - static Z_DiagRec *recp[1], rec; -#endif + Z_DiagRec **recp = odr_malloc (assoc->encode, sizeof(*recp)); + Z_DiagRec *drec = odr_malloc (assoc->encode, sizeof(*drec)); + Z_DefaultDiagFormat *rec = odr_malloc (assoc->encode, sizeof(*rec)); logf(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo); - bib1.proto = proto; + bib1.proto = assoc->proto; bib1.oclass = CLASS_DIAGSET; bib1.value = VAL_BIB1; - err = error; - recs.num_diagRecs = 1; - recs.diagRecs = recp; -#ifdef Z_95 - recp[0] = &drec; - drec.which = Z_DiagRec_defaultFormat; - drec.u.defaultFormat = &rec; -#else - recp[0] = &rec; -#endif - rec.diagnosticSetId = oid_getoidbyent(&bib1); - rec.condition = &err; - rec.which = Z_DiagForm_v2AddInfo; - rec.addinfo = addinfo ? addinfo : ""; - return &recs; + *err = error; + recs->num_diagRecs = 1; + recs->diagRecs = recp; + recp[0] = drec; + drec->which = Z_DiagRec_defaultFormat; + drec->u.defaultFormat = rec; + + rec->diagnosticSetId = oid_getoidbyent(&bib1); + rec->condition = err; + rec->which = Z_DiagForm_v2AddInfo; + rec->addinfo = addinfo ? addinfo : ""; + return recs; } -#define MAX_RECORDS 256 - static Z_Records *pack_records(association *a, char *setname, int start, int *num, Z_RecordComposition *comp, int *next, int *pres, oid_value format) { int recno, total_length = 0, toget = *num, dumped_records = 0; - static Z_Records records; - static Z_NamePlusRecordList reclist; - static Z_NamePlusRecord *list[MAX_RECORDS]; + Z_Records *records = odr_malloc (a->encode, sizeof(*records)); + Z_NamePlusRecordList *reclist = odr_malloc (a->encode, sizeof(*reclist)); + Z_NamePlusRecord **list = odr_malloc (a->encode, sizeof(*list) * toget); oident recform; - records.which = Z_Records_DBOSD; - records.u.databaseOrSurDiagnostics = &reclist; - reclist.num_records = 0; - reclist.records = list; + records->which = Z_Records_DBOSD; + records->u.databaseOrSurDiagnostics = reclist; + reclist->num_records = 0; + reclist->records = list; *pres = Z_PRES_SUCCESS; *num = 0; *next = 0; @@ -875,7 +866,7 @@ static Z_Records *pack_records(association *a, char *setname, int start, logf(LOG_DEBUG, "Request to pack %d+%d", start, toget); logf(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize, a->maximumRecordSize); - for (recno = start; reclist.num_records < toget; recno++) + for (recno = start; reclist->num_records < toget; recno++) { bend_fetchrequest freq; bend_fetchresult *fres; @@ -889,11 +880,6 @@ static Z_Records *pack_records(association *a, char *setname, int start, * idea of the total size of the data so far. */ total_length = odr_total(a->encode) - dumped_records; - if (reclist.num_records == MAX_RECORDS - 1) - { - *pres = Z_PRES_PARTIAL_2; - break; - } freq.setname = setname; freq.number = recno; freq.comp = comp; @@ -902,14 +888,14 @@ static Z_Records *pack_records(association *a, char *setname, int start, if (!(fres = bend_fetch(a->backend, &freq, 0))) { *pres = Z_PRES_FAILURE; - return diagrec(a->proto, 2, "Backend interface problem"); + return diagrec(a, 2, "Backend interface problem"); } /* backend should be able to signal whether error is system-wide or only pertaining to current record */ if (fres->errcode) { *pres = Z_PRES_FAILURE; - return diagrec(a->proto, fres->errcode, fres->errstring); + return diagrec(a, fres->errcode, fres->errstring); } if (fres->len >= 0) this_length = fres->len; @@ -933,9 +919,9 @@ static Z_Records *pack_records(association *a, char *setname, int start, if (toget > 1) { logf(LOG_DEBUG, " Dropped it"); - reclist.records[reclist.num_records] = - surrogatediagrec(a->proto, fres->basename, 16, 0); - reclist.num_records++; + reclist->records[reclist->num_records] = + surrogatediagrec(a, fres->basename, 16, 0); + reclist->num_records++; *next = fres->last_in_set ? 0 : recno + 1; dumped_records += this_length; continue; @@ -944,9 +930,9 @@ static Z_Records *pack_records(association *a, char *setname, int start, else /* too big entirely */ { logf(LOG_DEBUG, "Record > maxrcdsz"); - reclist.records[reclist.num_records] = - surrogatediagrec(a->proto, fres->basename, 17, 0); - reclist.num_records++; + reclist->records[reclist->num_records] = + surrogatediagrec(a, fres->basename, 17, 0); + reclist->num_records++; *next = fres->last_in_set ? 0 : recno + 1; dumped_records += this_length; continue; @@ -1016,12 +1002,12 @@ static Z_Records *pack_records(association *a, char *setname, int start, thisext->u.octet_aligned->len = thisext->u.octet_aligned->size = fres->len; } - reclist.records[reclist.num_records] = thisrec; - reclist.num_records++; + reclist->records[reclist->num_records] = thisrec; + reclist->num_records++; *next = fres->last_in_set ? 0 : recno + 1; } - *num = reclist.num_records; - return &records; + *num = reclist->num_records; + return records; } static Z_APDU *process_searchRequest(association *assoc, request *reqb, @@ -1057,20 +1043,23 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, bend_searchresult *bsrt, int *fd) { Z_SearchRequest *req = reqb->request->u.searchRequest; - static Z_APDU apdu; - static Z_SearchResponse resp; - static int nulint = 0; - static bool_t sr = 1; - static int next = 0; - static int none = Z_RES_NONE; - - apdu.which = Z_APDU_searchResponse; - apdu.u.searchResponse = &resp; - resp.referenceId = req->referenceId; -#ifdef Z_95 - resp.additionalSearchInfo = 0; - resp.otherInfo = 0; -#endif + Z_APDU *apdu = odr_malloc (assoc->encode, sizeof(*apdu)); + Z_SearchResponse *resp = odr_malloc (assoc->encode, sizeof(*resp)); + int *nulint = odr_malloc (assoc->encode, sizeof(*nulint)); + bool_t *sr = odr_malloc (assoc->encode, sizeof(*sr)); + int *next = odr_malloc (assoc->encode, sizeof(*next)); + int *none = odr_malloc (assoc->encode, sizeof(*none)); + + *nulint = 0; + *sr = 1; + *next = 0; + *none = Z_RES_NONE; + + apdu->which = Z_APDU_searchResponse; + apdu->u.searchResponse = resp; + resp->referenceId = req->referenceId; + resp->additionalSearchInfo = 0; + resp->otherInfo = 0; *fd = -1; if (!bsrt && !(bsrt = bend_searchresponse(assoc->backend))) { @@ -1079,44 +1068,45 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, } else if (bsrt->errcode) { - resp.records = diagrec(assoc->proto, bsrt->errcode, - bsrt->errstring); - resp.resultCount = &nulint; - resp.numberOfRecordsReturned = &nulint; - resp.nextResultSetPosition = &nulint; - resp.searchStatus = &nulint; - resp.resultSetStatus = &none; - resp.presentStatus = 0; + resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring); + resp->resultCount = nulint; + resp->numberOfRecordsReturned = nulint; + resp->nextResultSetPosition = nulint; + resp->searchStatus = nulint; + resp->resultSetStatus = none; + resp->presentStatus = 0; } else { - static int toget; + int *toget = odr_malloc (assoc->encode, sizeof(*toget)); + int *presst = odr_malloc (assoc->encode, sizeof(*presst)); Z_RecordComposition comp, *compp = 0; - static int presst = 0; - resp.records = 0; - resp.resultCount = &bsrt->hits; + *toget = 0; + *presst = 0; + resp->records = 0; + resp->resultCount = &bsrt->hits; comp.which = Z_RecordComp_simple; /* how many records does the user agent want, then? */ if (bsrt->hits <= *req->smallSetUpperBound) { - toget = bsrt->hits; + *toget = bsrt->hits; if ((comp.u.simple = req->smallSetElementSetNames)) compp = ∁ } else if (bsrt->hits < *req->largeSetLowerBound) { - toget = *req->mediumSetPresentNumber; - if (toget > bsrt->hits) - toget = bsrt->hits; + *toget = *req->mediumSetPresentNumber; + if (*toget > bsrt->hits) + *toget = bsrt->hits; if ((comp.u.simple = req->mediumSetElementSetNames)) compp = ∁ } else - toget = 0; + *toget = 0; - if (toget && !resp.records) + if (*toget && !resp->records) { oident *prefformat; oid_value form; @@ -1126,28 +1116,28 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, form = VAL_NONE; else form = prefformat->value; - resp.records = pack_records(assoc, req->resultSetName, 1, - &toget, compp, &next, &presst, form); - if (!resp.records) + resp->records = pack_records(assoc, req->resultSetName, 1, + toget, compp, next, presst, form); + if (!resp->records) return 0; - resp.numberOfRecordsReturned = &toget; - resp.nextResultSetPosition = &next; - resp.searchStatus = &sr; - resp.resultSetStatus = 0; - resp.presentStatus = &presst; + resp->numberOfRecordsReturned = toget; + resp->nextResultSetPosition = next; + resp->searchStatus = sr; + resp->resultSetStatus = 0; + resp->presentStatus = presst; } else { - if (*resp.resultCount) - next = 1; - resp.numberOfRecordsReturned = &nulint; - resp.nextResultSetPosition = &next; - resp.searchStatus = &sr; - resp.resultSetStatus = 0; - resp.presentStatus = 0; + if (*resp->resultCount) + *next = 1; + resp->numberOfRecordsReturned = nulint; + resp->nextResultSetPosition = next; + resp->searchStatus = sr; + resp->resultSetStatus = 0; + resp->presentStatus = 0; } } - return &apdu; + return apdu; } /* @@ -1169,37 +1159,40 @@ static Z_APDU *process_presentRequest(association *assoc, request *reqb, int *fd) { Z_PresentRequest *req = reqb->request->u.presentRequest; - static Z_APDU apdu; - static Z_PresentResponse resp; - static int presst, next, num; + Z_APDU *apdu = odr_malloc (assoc->encode, sizeof(*apdu)); + Z_PresentResponse *resp = odr_malloc (assoc->encode, sizeof(*resp)); + int *presst = odr_malloc (assoc->encode, sizeof(*presst)); + int *next = odr_malloc (assoc->encode, sizeof(*next)); + int *num = odr_malloc (assoc->encode, sizeof(*num)); oident *prefformat; oid_value form; - logf(LOG_LOG, "Got PresentRequest."); - apdu.which = Z_APDU_presentResponse; - apdu.u.presentResponse = &resp; - resp.referenceId = req->referenceId; -#ifdef Z_95 - resp.otherInfo = 0; -#endif + *presst = 0; + *next = 0; + *num = 0; + + apdu->which = Z_APDU_presentResponse; + apdu->u.presentResponse = resp; + resp->referenceId = req->referenceId; + resp->otherInfo = 0; if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)) || prefformat->oclass != CLASS_RECSYN) form = VAL_NONE; else form = prefformat->value; - num = *req->numberOfRecordsRequested; - resp.records = pack_records(assoc, req->resultSetId, - *req->resultSetStartPoint, &num, req->recordComposition, &next, - &presst, form); - if (!resp.records) + *num = *req->numberOfRecordsRequested; + resp->records = pack_records(assoc, req->resultSetId, + *req->resultSetStartPoint, num, req->recordComposition, next, + presst, form); + if (!resp->records) return 0; - resp.numberOfRecordsReturned = # - resp.presentStatus = &presst; - resp.nextResultSetPosition = &next; + resp->numberOfRecordsReturned = num; + resp->presentStatus = presst; + resp->nextResultSetPosition = next; - return &apdu; + return apdu; } /* @@ -1209,38 +1202,38 @@ static Z_APDU *process_presentRequest(association *assoc, request *reqb, static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) { Z_ScanRequest *req = reqb->request->u.scanRequest; - static Z_APDU apdu; - static Z_ScanResponse res; - static int scanStatus = Z_Scan_failure; - static int numberOfEntriesReturned = 0; + Z_APDU *apdu = odr_malloc (assoc->encode, sizeof(*apdu)); + Z_ScanResponse *res = odr_malloc (assoc->encode, sizeof(*res)); + int *scanStatus = odr_malloc (assoc->encode, sizeof(*scanStatus)); + int *numberOfEntriesReturned = + odr_malloc (assoc->encode, sizeof(*numberOfEntriesReturned)); + Z_ListEntries *ents = odr_malloc (assoc->encode, sizeof(*ents)); oident *attent; - static Z_ListEntries ents; -#define SCAN_MAX_ENTRIES 200 - static Z_Entry *tab[SCAN_MAX_ENTRIES]; bend_scanrequest srq; bend_scanresult *srs; oident *attset; logf(LOG_LOG, "Got scanrequest"); - apdu.which = Z_APDU_scanResponse; - apdu.u.scanResponse = &res; - res.referenceId = req->referenceId; - res.stepSize = 0; - res.scanStatus = &scanStatus; - res.numberOfEntriesReturned = &numberOfEntriesReturned; - res.positionOfTerm = 0; - res.entries = &ents; - ents.which = Z_ListEntries_nonSurrogateDiagnostics; - res.attributeSet = 0; -#ifdef Z_95 - res.otherInfo = 0; -#endif + *scanStatus = Z_Scan_failure; + *numberOfEntriesReturned = 0; + + apdu->which = Z_APDU_scanResponse; + apdu->u.scanResponse = res; + res->referenceId = req->referenceId; + res->stepSize = 0; + res->scanStatus = scanStatus; + res->numberOfEntriesReturned = numberOfEntriesReturned; + res->positionOfTerm = 0; + res->entries = ents; + ents->which = Z_ListEntries_nonSurrogateDiagnostics; + res->attributeSet = 0; + res->otherInfo = 0; if (req->attributeSet && (!(attent = oid_getentbyoid(req->attributeSet)) || attent->oclass != CLASS_ATTSET || attent->value != VAL_BIB1)) - ents.u.nonSurrogateDiagnostics = diagrecs(assoc->proto, 121, 0); + ents->u.nonSurrogateDiagnostics = diagrecs(assoc, 121, 0); else if (req->stepSize && *req->stepSize > 0) - ents.u.nonSurrogateDiagnostics = diagrecs(assoc->proto, 205, 0); + ents->u.nonSurrogateDiagnostics = diagrecs(assoc, 205, 0); else { if (req->termListAndStartPoint->term->which == Z_Term_general) @@ -1259,34 +1252,31 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) srq.term_position = req->preferredPositionInResponse ? *req->preferredPositionInResponse : 1; if (!(srs = bend_scan(assoc->backend, &srq, 0))) - ents.u.nonSurrogateDiagnostics = diagrecs(assoc->proto, 2, 0); + ents->u.nonSurrogateDiagnostics = diagrecs(assoc, 2, 0); else if (srs->errcode) - ents.u.nonSurrogateDiagnostics = diagrecs(assoc->proto, + ents->u.nonSurrogateDiagnostics = diagrecs(assoc, srs->errcode, srs->errstring); else { int i; - static Z_Entries list; + Z_Entries *list = odr_malloc (assoc->encode, sizeof(*list)); + Z_Entry **tab = odr_malloc (assoc->encode, + sizeof(*tab) * srs->num_entries); if (srs->status == BEND_SCAN_PARTIAL) - scanStatus = Z_Scan_partial_5; + *scanStatus = Z_Scan_partial_5; else - scanStatus = Z_Scan_success; - ents.which = Z_ListEntries_entries; - ents.u.entries = &list; - list.entries = tab; + *scanStatus = Z_Scan_success; + ents->which = Z_ListEntries_entries; + ents->u.entries = list; + list->entries = tab; for (i = 0; i < srs->num_entries; i++) { Z_Entry *e; Z_TermInfo *t; Odr_oct *o; - if (i >= SCAN_MAX_ENTRIES) - { - scanStatus = Z_Scan_partial_4; - break; - } - list.entries[i] = e = odr_malloc(assoc->encode, sizeof(*e)); + list->entries[i] = e = odr_malloc(assoc->encode, sizeof(*e)); e->which = Z_Entry_termInfo; e->u.termInfo = t = odr_malloc(assoc->encode, sizeof(*t)); t->suggestedAttributes = 0; @@ -1305,13 +1295,13 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) logf(LOG_DEBUG, " term #%d: '%s' (%d)", i, srs->entries[i].term, srs->entries[i].occurrences); } - list.num_entries = i; - res.numberOfEntriesReturned = &list.num_entries; - res.positionOfTerm = &srs->term_position; + list->num_entries = i; + res->numberOfEntriesReturned = &list->num_entries; + res->positionOfTerm = &srs->term_position; } } - return &apdu; + return apdu; } static void process_close(association *assoc, request *reqb) diff --git a/server/session.h b/server/session.h index ab63da3..aefe3da 100644 --- a/server/session.h +++ b/server/session.h @@ -4,7 +4,12 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: session.h,v $ - * Revision 1.11 1995-11-08 17:41:40 quinn + * Revision 1.12 1997-09-01 08:53:01 adam + * New windows NT/95 port using MSV5.0. The test server 'ztest' was + * moved a separate directory. MSV5.0 project server.dsp created. + * As an option, the server can now operate as an NT service. + * + * Revision 1.11 1995/11/08 17:41:40 quinn * Smallish. * * Revision 1.10 1995/08/29 11:18:01 quinn @@ -49,7 +54,7 @@ #include #include #include -#include +#include "eventl.h" typedef struct request { @@ -69,12 +74,14 @@ typedef struct request char *response; /* encoded data waiting for transmission */ struct request *next; + struct request_q *q; } request; typedef struct request_q { request *head; request *tail; + request *list; int num; } request_q; @@ -118,7 +125,8 @@ void request_enq(request_q *q, request *r); request *request_head(request_q *q); request *request_deq(request_q *q); void request_initq(request_q *q); -request *request_get(void); +void request_delq(request_q *q); +request *request_get(request_q *q); void request_release(request *r); #endif diff --git a/server/statserv.c b/server/statserv.c index 3f86861..a09ba6b 100644 --- a/server/statserv.c +++ b/server/statserv.c @@ -4,7 +4,12 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: statserv.c,v $ - * Revision 1.36 1996-07-06 19:58:36 quinn + * Revision 1.37 1997-09-01 08:53:01 adam + * New windows NT/95 port using MSV5.0. The test server 'ztest' was + * moved a separate directory. MSV5.0 project server.dsp created. + * As an option, the server can now operate as an NT service. + * + * Revision 1.36 1996/07/06 19:58:36 quinn * System headerfiles gathered in yconfig * * Revision 1.35 1996/05/29 10:03:28 quinn @@ -123,16 +128,21 @@ #include #include +#ifdef WINDOWS +#include +#include +#include +#else #include +#include +#endif #include #include #include -#include #include -#include -#include -#include +#include "eventl.h" +#include "session.h" #include #include #ifdef USE_XTIMOSI @@ -141,6 +151,8 @@ #include #include +static IOCHAN pListener; + static char *me = "statserver"; /* * default behavior. @@ -164,6 +176,249 @@ static statserv_options_block control_block = { * doing all of the listening and accepting in the parent - it's * safer that way. */ +#ifdef WINDOWS + +typedef struct _ThreadList ThreadList; + +typedef struct _ThreadList +{ + HANDLE hThread; + IOCHAN pIOChannel; + ThreadList *pNext; +} ThreadList; + +static ThreadList *pFirstThread; +static CRITICAL_SECTION Thread_CritSect; +static BOOL bInitialized = FALSE; + +static void ThreadList_Initialize() +{ + /* Initialize the critical Sections */ + InitializeCriticalSection(&Thread_CritSect); + + /* Set the first thraed */ + pFirstThread = NULL; + + /* we have been initialized */ + bInitialized = TRUE; +} + +static void statserv_add(HANDLE hThread, IOCHAN pIOChannel) +{ + /* Only one thread can go through this section at a time */ + EnterCriticalSection(&Thread_CritSect); + + { + /* Lets create our new object */ + ThreadList *pNewThread = (ThreadList *)malloc(sizeof(ThreadList)); + pNewThread->hThread = hThread; + pNewThread->pIOChannel = pIOChannel; + pNewThread->pNext = pFirstThread; + pFirstThread = pNewThread; + + /* Lets let somebody else create a new object now */ + LeaveCriticalSection(&Thread_CritSect); + } +} + +void statserv_remove(IOCHAN pIOChannel) +{ + /* Only one thread can go through this section at a time */ + EnterCriticalSection(&Thread_CritSect); + + { + ThreadList *pCurrentThread = pFirstThread; + ThreadList *pNextThread; + ThreadList *pPrevThread =NULL; + + /* Step through alll the threads */ + for (; pCurrentThread != NULL; pCurrentThread = pNextThread) + { + /* We only need to compare on the IO Channel */ + if (pCurrentThread->pIOChannel == pIOChannel) + { + /* We have found the thread we want to delete */ + /* First of all reset the next pointers */ + if (pPrevThread == NULL) + pFirstThread = pCurrentThread->pNext; + else + pPrevThread->pNext = pCurrentThread->pNext; + + /* All we need todo now is delete the memory */ + free(pCurrentThread); + + /* No need to look at any more threads */ + pNextThread = NULL; + } + else + { + /* We need to look at another thread */ + pNextThread = pCurrentThread->pNext; + } + } + + /* Lets let somebody else remove an object now */ + LeaveCriticalSection(&Thread_CritSect); + } +} + +void statserv_closedown() +{ + /* Shouldn't do anything if we are not initialized */ + if (bInitialized) + { + int iHandles = 0; + HANDLE *pThreadHandles = NULL; + + /* We need to stop threads adding and removing while we start the closedown process */ + EnterCriticalSection(&Thread_CritSect); + + { + /* We have exclusive access to the thread stuff now */ + /* Y didn't i use a semaphore - Oh well never mind */ + ThreadList *pCurrentThread = pFirstThread; + + /* Before we do anything else, we need to shutdown the listener */ + if (pListener != NULL) + iochan_destroy(pListener); + + for (; pCurrentThread != NULL; pCurrentThread = pCurrentThread->pNext) + { + /* Just destroy the IOCHAN, that should do the trick */ + iochan_destroy(pCurrentThread->pIOChannel); + + /* Keep a running count of our handles */ + iHandles++; + } + + if (iHandles > 0) + { + HANDLE *pCurrentHandle ; + + /* Allocate the thread handle array */ + pThreadHandles = (HANDLE *)malloc(sizeof(HANDLE) * iHandles); + pCurrentHandle = pThreadHandles; + + for (pCurrentThread = pFirstThread; + pCurrentThread != NULL; + pCurrentThread = pCurrentThread->pNext, pCurrentHandle++) + { + /* Just the handle */ + *pCurrentHandle = pCurrentThread->hThread; + } + } + + /* We can now leave the critical section */ + LeaveCriticalSection(&Thread_CritSect); + } + + /* Now we can really do something */ + if (iHandles > 0) + { + /* This will now wait, until all the threads close */ + WaitForMultipleObjects(iHandles, pThreadHandles, TRUE, INFINITE); + + /* Free the memory we allocated for the handle array */ + free(pThreadHandles); + } + + /* No longer require the critical section, since all threads are dead */ + DeleteCriticalSection(&Thread_CritSect); + } +} + +static void listener(IOCHAN h, int event) +{ + COMSTACK line = (COMSTACK) iochan_getdata(h); + association *newas; + int res; + HANDLE NewHandle; + + if (event == EVENT_INPUT) + { + if ((res = cs_listen(line, 0, 0)) < 0) + { + logf(LOG_FATAL, "cs_listen failed."); + return; + } + else if (res == 1) + return; + logf(LOG_DEBUG, "listen ok"); + iochan_setevent(h, EVENT_OUTPUT); + iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */ + } + else if (event == EVENT_OUTPUT) + { + COMSTACK new_line; + IOCHAN new_chan; + char *a; + DWORD ThreadId; + + if (!(new_line = cs_accept(line))) + { + logf(LOG_FATAL, "Accept failed."); + iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ + return; + } + logf(LOG_DEBUG, "accept ok"); + + if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, EVENT_INPUT))) + { + logf(LOG_FATAL, "Failed to create iochan"); + iochan_destroy(h); + return; + } + if (!(newas = create_association(new_chan, new_line))) + { + logf(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]"); + + /* Now what we need todo is create a new thread with this iochan as the parameter */ +/* if (CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)event_loop, new_chan, 0, &ThreadId) == NULL) +*/ + /* Somehow, somewhere we need to store this thread id, otherwise we won't be able to close cleanly */ + NewHandle = (HANDLE)_beginthreadex(NULL, 0, event_loop, new_chan, 0, &ThreadId); + if (NewHandle == (HANDLE)-1) + { + logf(LOG_FATAL, "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); + iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ + } + else + { + logf(LOG_FATAL, "Bad event on listener."); + iochan_destroy(h); + return; + } +} + +#else /* WINDOWS */ + +/* To save having an #ifdef in event_loop we need to define this empty function */ +void statserv_remove(IOCHAN pIOChannel) +{ +} + +void statserv_closedown() +{ + /* We don't need todoanything here - or do we */ + if (pListener != NULL) + iochan_destroy(pListener); +} + static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); @@ -181,12 +436,14 @@ static void listener(IOCHAN h, int event) if (pipe(hand) < 0) { logf(LOG_FATAL|LOG_ERRNO, "pipe"); - exit(1); + iochan_destroy(h); + return; } if ((res = fork()) < 0) { logf(LOG_FATAL|LOG_ERRNO, "fork"); - exit(1); + iochan_destroy(h); + return; } else if (res == 0) /* child */ { @@ -219,7 +476,7 @@ static void listener(IOCHAN h, int event) if ((res = read(hand[0], dummy, 1)) < 0 && errno != EINTR) { logf(LOG_FATAL|LOG_ERRNO, "handshake read"); - exit(1); + return; } else if (res >= 0) break; @@ -275,12 +532,14 @@ static void listener(IOCHAN h, int event) EVENT_INPUT))) { logf(LOG_FATAL, "Failed to create iochan"); - exit(1); + iochan_destroy(h); + return; } if (!(newas = create_association(new_chan, new_line))) { logf(LOG_FATAL, "Failed to create new assoc."); - exit(1); + iochan_destroy(h); + return; } iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, control_block.idle_timeout * 60); @@ -290,10 +549,13 @@ static void listener(IOCHAN h, int event) else { logf(LOG_FATAL, "Bad event on listener."); - exit(1); + iochan_destroy(h); + return; } } +#endif /* WINDOWS */ + static void inetd_connection(int what) { COMSTACK line; @@ -301,25 +563,31 @@ static void inetd_connection(int what) association *assoc; char *addr; - if (!(line = cs_createbysocket(0, tcpip_type, 0, what))) + if ((line = cs_createbysocket(0, tcpip_type, 0, what))) { - logf(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0"); - exit(1); - } - if (!(chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT))) - { - logf(LOG_FATAL, "Failed to create iochan"); - exit(1); + if ((chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT))) + { + if ((assoc = create_association(chan, line))) + { + 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]"); + } + else + { + logf(LOG_FATAL, "Failed to create association structure"); + } + } + else + { + logf(LOG_FATAL, "Failed to create iochan"); + } } - if (!(assoc = create_association(chan, line))) + else { - logf(LOG_FATAL, "Failed to create association structure"); - exit(1); + logf(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0"); } - 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]"); } /* @@ -331,20 +599,18 @@ static void add_listener(char *where, int what) CS_TYPE type; char mode[100], addr[100]; void *ap; - IOCHAN lst; + IOCHAN lst = NULL; if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2) { fprintf(stderr, "%s: Address format: ('tcp'|'osi')':'
.\n", me); - exit(1); } if (!strcmp(mode, "tcp")) { if (!(ap = tcpip_strtoaddr(addr))) { fprintf(stderr, "Address resolution failed for TCP.\n"); - exit(1); } type = tcpip_type; } @@ -354,18 +620,15 @@ static void add_listener(char *where, int what) if (!(ap = mosi_strtoaddr(addr))) { fprintf(stderr, "Address resolution failed for TCP.\n"); - exit(1); } type = mosi_type; #else fprintf(stderr, "OSI Transport not allowed by configuration.\n"); - exit(1); #endif } else { fprintf(stderr, "You must specify either 'osi:' or 'tcp:'.\n"); - exit(1); } logf(LOG_LOG, "Adding %s %s listener on %s", control_block.dynamic ? "dynamic" : "static", @@ -373,28 +636,32 @@ static void add_listener(char *where, int what) if (!(l = cs_create(type, 0, what))) { logf(LOG_FATAL|LOG_ERRNO, "Failed to create listener"); - exit(1); } if (cs_bind(l, ap, CS_SERVER) < 0) { logf(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where); - exit(1); } if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT | EVENT_EXCEPT))) { logf(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type"); - exit(1); } iochan_setdata(lst, l); + + /* Ensure our listener chain is setup properly */ + lst->next = pListener; + pListener = lst; } +#ifndef WINDOWS +/* For windows we don't need to catch the signals */ static void catchchld(int num) { while (waitpid(-1, 0, WNOHANG) > 0) ; signal(SIGCHLD, catchchld); } +#endif /* WINDOWS */ statserv_options_block *statserv_getcontrol(void) { @@ -415,14 +682,19 @@ int statserv_main(int argc, char **argv) char *arg; int protocol = control_block.default_proto; +#ifdef WINDOWS + /* We need to initialize the thread list */ + ThreadList_Initialize(); +#endif /* WINDOWS */ + me = argv[0]; while ((ret = options("a:iszSl:v:u:c:w:t:k:", argv, argc, &arg)) != -2) { switch (ret) { case 0: - add_listener(arg, protocol); - listeners++; + add_listener(arg, protocol); + listeners++; break; case 'z': protocol = PROTO_Z3950; break; case 's': protocol = PROTO_SR; break; @@ -446,7 +718,7 @@ int statserv_main(int argc, char **argv) { fprintf(stderr, "%s: Specify positive timeout for -t.\n", me); - exit(1); + return(1); } control_block.idle_timeout = r; break; @@ -455,7 +727,7 @@ int statserv_main(int argc, char **argv) { fprintf(stderr, "%s: Specify positive timeout for -t.\n", me); - exit(1); + return(1); } control_block.maxrecordsize = r * 1024; break; @@ -465,7 +737,8 @@ int statserv_main(int argc, char **argv) if (chdir(arg)) { perror(arg); - exit(1); + + return(1); } break; default: @@ -473,17 +746,24 @@ int statserv_main(int argc, char **argv) " -l -u -c -t " " -k " " -zsS -w ... ]\n", me); - exit(1); + return(1); } } + +#ifdef WINDOWS + log_init(control_block.loglevel, NULL, control_block.logfile); +#endif /* WINDOWS */ + + if ((pListener == NULL) && *control_block.default_listen) + add_listener(control_block.default_listen, protocol); + +#ifndef WINDOWS if (inetd) inetd_connection(protocol); else { if (control_block.dynamic) signal(SIGCHLD, catchchld); - if (!listeners && *control_block.default_listen) - add_listener(control_block.default_listen, protocol); } if (*control_block.setuid) { @@ -492,7 +772,7 @@ int statserv_main(int argc, char **argv) if (!(pw = getpwnam(control_block.setuid))) { logf(LOG_FATAL, "%s: Unknown user", control_block.setuid); - exit(1); + return(1); } if (setuid(pw->pw_uid) < 0) { @@ -500,7 +780,12 @@ int statserv_main(int argc, char **argv) exit(1); } } +#endif /* WINDOWS */ + logf(LOG_LOG, "Entering event loop."); - - return event_loop(); + + if (pListener == NULL) + return(1); + else + return event_loop(pListener); }