+++ /dev/null
-/*
- * Copyright (c) 1995-2003, Index Data
- * See the file LICENSE for details.
- * Sebastian Hammer, Adam Dickmeiss
- *
- * NT threaded server code by
- * Chas Woodfield, Fretwell Downing Informatics.
- *
- * $Id: statserv.c,v 1.98 2003-03-03 19:57:35 adam Exp $
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef WIN32
-#include <process.h>
-#include <winsock.h>
-#include <direct.h>
-#include "service.h"
-#else
-#include <unistd.h>
-#include <pwd.h>
-#endif
-
-#if YAZ_POSIX_THREADS
-#include <pthread.h>
-#elif YAZ_GNU_THREADS
-#include <pth.h>
-#endif
-
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-
-#include <yaz/comstack.h>
-#include <yaz/tcpip.h>
-#include <yaz/options.h>
-#ifdef USE_XTIMOSI
-#include <yaz/xmosi.h>
-#endif
-#include <yaz/log.h>
-#include "eventl.h"
-#include "session.h"
-#include <yaz/statserv.h>
-
-static IOCHAN pListener = NULL;
-
-static char *me = "statserver";
-/*
- * default behavior.
- */
-int check_options(int argc, char **argv);
-statserv_options_block control_block = {
- 1, /* dynamic mode */
- 0, /* threaded mode */
- 0, /* one shot (single session) */
- LOG_DEFAULT_LEVEL, /* log level */
- "", /* no PDUs */
- "", /* diagnostic output to stderr */
- "tcp:@:9999", /* default listener port */
- PROTO_Z3950, /* default application protocol */
- 15, /* idle timeout (minutes) */
- 1024*1024, /* maximum PDU size (approx.) to allow */
- "default-config", /* configuration name to pass to backend */
- "", /* set user id */
- 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 */
- 0, /* handle (for service, etc) */
- 0, /* bend_init handle */
- 0, /* bend_close handle */
-#ifdef WIN32
- "Z39.50 Server", /* NT Service Name */
- "Server", /* NT application Name */
- "", /* NT Service Dependencies */
- "Z39.50 Server", /* NT Service Display Name */
-#endif /* WIN32 */
- 0 /* SOAP handlers */
-};
-
-static int max_sessions = 0;
-
-/*
- * handle incoming connect requests.
- * The dynamic mode is a bit tricky mostly because we want to avoid
- * doing all of the listening and accepting in the parent - it's
- * safer that way.
- */
-#ifdef WIN32
-
-typedef struct _ThreadList ThreadList;
-
-struct _ThreadList
-{
- HANDLE hThread;
- IOCHAN pIOChannel;
- ThreadList *pNext;
-};
-
-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;
- pPrevThread = pCurrentThread;
- }
- }
-
- /* Lets let somebody else remove an object now */
- LeaveCriticalSection(&Thread_CritSect);
- }
-}
-
-/* WIN32 statserv_closedown */
-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);
- closesocket(pCurrentThread->pIOChannel->fd);
-
- /* 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)
- {
- logf (LOG_LOG, "waiting for %d to die", iHandles);
- /* 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);
- }
-
- 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);
- }
-}
-
-void __cdecl event_loop_thread (IOCHAN iochan)
-{
- event_loop (&iochan);
-}
-
-/* WIN32 listener */
-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)
- {
- yaz_log(LOG_FATAL, "cs_listen failed");
- return;
- }
- else if (res == 1)
- return;
- yaz_log(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 = cs_accept(line);
- IOCHAN new_chan;
- char *a = NULL;
-
- if (!new_line)
- {
- yaz_log(LOG_FATAL, "Accept failed.");
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT);
- return;
- }
- yaz_log(LOG_DEBUG, "Accept ok");
-
- if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
- EVENT_INPUT)))
- {
- yaz_log(LOG_FATAL, "Failed to create iochan");
- iochan_destroy(h);
- return;
- }
-
- yaz_log(LOG_DEBUG, "Creating association");
- if (!(newas = create_association(new_chan, new_line)))
- {
- yaz_log(LOG_FATAL, "Failed to create new assoc.");
- iochan_destroy(h);
- return;
- }
- newas->cs_get_mask = EVENT_INPUT;
- newas->cs_put_mask = 0;
- newas->cs_accept_mask = 0;
-
- yaz_log(LOG_DEBUG, "Setting timeout %d", control_block.idle_timeout);
- iochan_setdata(new_chan, newas);
- iochan_settimeout(new_chan, 60);
-
- /* Now what we need todo is create a new thread with this iochan as
- the parameter */
- newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan);
- if (newHandle == (HANDLE) -1)
- {
-
- 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);
-
- yaz_log(LOG_DEBUG, "Created new thread, id = %ld iochan %p",(long) newHandle, new_chan);
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
- }
- else
- {
- yaz_log(LOG_FATAL, "Bad event on listener.");
- iochan_destroy(h);
- return;
- }
-}
-
-int statserv_must_terminate(void)
-{
- return 0;
-}
-
-#else /* ! WIN32 */
-
-static int term_flag = 0;
-/* To save having an #ifdef in event_loop we need to
- define this empty function
-*/
-int statserv_must_terminate(void)
-{
- return term_flag;
-}
-
-void statserv_remove(IOCHAN pIOChannel)
-{
-}
-
-void statserv_closedown()
-{
- IOCHAN p;
-
- if (control_block.bend_stop)
- (*control_block.bend_stop)(&control_block);
- for (p = pListener; p; p = p->next)
- {
- iochan_destroy(p);
- }
-}
-
-void sigterm(int sig)
-{
- term_flag = 1;
-}
-
-static void *new_session (void *vp);
-static int no_sessions = 0;
-
-/* UNIX listener */
-static void listener(IOCHAN h, int event)
-{
- COMSTACK line = (COMSTACK) iochan_getdata(h);
- static int hand[2];
- static int child = 0;
- int res;
-
- if (event == EVENT_INPUT)
- {
- if (control_block.dynamic && !child)
- {
- int res;
-
- ++no_sessions;
- if (pipe(hand) < 0)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "pipe");
- iochan_destroy(h);
- return;
- }
- if ((res = fork()) < 0)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "fork");
- iochan_destroy(h);
- return;
- }
- else if (res == 0) /* child */
- {
- char nbuf[100];
- IOCHAN pp;
-
- close(hand[0]);
- child = 1;
- for (pp = pListener; pp; pp = iochan_getnext(pp))
- {
- if (pp != h)
- {
- COMSTACK l = (COMSTACK)iochan_getdata(pp);
- cs_close(l);
- iochan_destroy(pp);
- }
- }
- sprintf(nbuf, "%s(%d)", me, getpid());
- yaz_log_init(control_block.loglevel, nbuf, 0);
- /* ensure that bend_stop is not called when each child exits -
- only for the main process ..
- */
- control_block.bend_stop = 0;
- }
- else /* parent */
- {
- close(hand[1]);
- /* wait for child to take the call */
- for (;;)
- {
- char dummy[1];
- int res;
-
- if ((res = read(hand[0], dummy, 1)) < 0 &&
- yaz_errno() != EINTR)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "handshake read");
- return;
- }
- else if (res >= 0)
- break;
- }
- yaz_log(LOG_DEBUG, "P: Child has taken the call");
- close(hand[0]);
- return;
- }
- }
- if ((res = cs_listen_check(line, 0, 0, control_block.check_ip,
- control_block.daemon_name)) < 0)
- {
- yaz_log(LOG_WARN|LOG_ERRNO, "cs_listen failed");
- return;
- }
- else if (res == 1)
- return;
- yaz_log(LOG_DEBUG, "listen ok");
- iochan_setevent(h, EVENT_OUTPUT);
- iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
- }
- /* in dynamic mode, only the child ever comes down here */
- else if (event == EVENT_OUTPUT)
- {
- COMSTACK new_line = cs_accept(line);
-
- if (!new_line)
- {
- yaz_log(LOG_FATAL, "Accept failed.");
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
- return;
- }
- yaz_log(LOG_DEBUG, "accept ok");
- if (control_block.dynamic)
- {
- IOCHAN pp;
- /* close our half of the listener socket */
- for (pp = pListener; pp; pp = iochan_getnext(pp))
- {
- COMSTACK l = (COMSTACK)iochan_getdata(pp);
- cs_close(l);
- iochan_destroy(pp);
- }
- /* release dad */
- yaz_log(LOG_DEBUG, "Releasing parent");
- close(hand[1]);
- }
- else
- {
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
- ++no_sessions;
- }
-#if YAZ_POSIX_THREADS
- if (control_block.threads)
- {
- pthread_t child_thread;
- pthread_create (&child_thread, 0, new_session, new_line);
- pthread_detach (child_thread);
- }
- else
- new_session(new_line);
-#elif YAZ_GNU_THREADS
- if (control_block.threads)
- {
- pth_attr_t attr;
- pth_t child_thread;
-
- attr = pth_attr_new ();
- pth_attr_set (attr, PTH_ATTR_JOINABLE, FALSE);
- pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 32*1024);
- pth_attr_set (attr, PTH_ATTR_NAME, "session");
- yaz_log (LOG_LOG, "pth_spawn begin");
- child_thread = pth_spawn (attr, new_session, new_line);
- yaz_log (LOG_LOG, "pth_spawn finish");
- pth_attr_destroy (attr);
- }
- else
- new_session(new_line);
-#else
- new_session(new_line);
-#endif
- }
- else if (event == EVENT_TIMEOUT)
- {
- yaz_log(LOG_LOG, "Shutting down listener.");
- iochan_destroy(h);
- }
- else
- {
- yaz_log(LOG_FATAL, "Bad event on listener.");
- iochan_destroy(h);
- }
-}
-
-static void *new_session (void *vp)
-{
- char *a;
- association *newas;
- IOCHAN new_chan;
- COMSTACK new_line = (COMSTACK) vp;
-
- unsigned cs_get_mask, cs_accept_mask, mask =
- ((new_line->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) |
- ((new_line->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0);
-
- if (mask)
- {
- cs_accept_mask = mask; /* accept didn't complete */
- cs_get_mask = 0;
- }
- else
- {
- cs_accept_mask = 0; /* accept completed. */
- cs_get_mask = mask = EVENT_INPUT;
- }
-
- if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, mask)))
- {
- yaz_log(LOG_FATAL, "Failed to create iochan");
- return 0;
- }
- if (!(newas = create_association(new_chan, new_line)))
- {
- yaz_log(LOG_FATAL, "Failed to create new assoc.");
- return 0;
- }
- newas->cs_accept_mask = cs_accept_mask;
- newas->cs_get_mask = cs_get_mask;
-
- iochan_setdata(new_chan, newas);
- iochan_settimeout(new_chan, 60);
-#if 1
- a = cs_addrstr(new_line);
-#else
- a = 0;
-#endif
- yaz_log(LOG_LOG, "Starting session %d from %s",
- no_sessions, a ? a : "[Unknown]");
- if (max_sessions && no_sessions == max_sessions)
- control_block.one_shot = 1;
- if (control_block.threads)
- {
- event_loop(&new_chan);
- }
- else
- {
- new_chan->next = pListener;
- pListener = new_chan;
- }
- return 0;
-}
-
-/* UNIX */
-#endif
-
-static void inetd_connection(int what)
-{
- COMSTACK line;
- IOCHAN chan;
- association *assoc;
- char *addr;
-
- if ((line = cs_createbysocket(0, tcpip_type, 0, what)))
- {
- if ((chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT)))
- {
- if ((assoc = create_association(chan, line)))
- {
- iochan_setdata(chan, assoc);
- iochan_settimeout(chan, 60);
- addr = cs_addrstr(line);
- yaz_log(LOG_LOG, "Inetd association from %s",
- addr ? addr : "[UNKNOWN]");
- assoc->cs_get_mask = EVENT_INPUT;
- }
- else
- {
- yaz_log(LOG_FATAL, "Failed to create association structure");
- }
- chan->next = pListener;
- pListener = chan;
- }
- else
- {
- yaz_log(LOG_FATAL, "Failed to create iochan");
- }
- }
- else
- {
- yaz_log(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0");
- }
-}
-
-/*
- * Set up a listening endpoint, and give it to the event-handler.
- */
-static int add_listener(char *where, int what)
-{
- COMSTACK l;
- void *ap;
- IOCHAN lst = NULL;
- const char *mode;
-
- if (control_block.dynamic)
- mode = "dynamic";
- else if (control_block.threads)
- mode = "threaded";
- else
- mode = "static";
-
- yaz_log(LOG_LOG, "Adding %s %s listener on %s", mode,
- what == PROTO_SR ? "SR" : "Z3950", where);
-
- l = cs_create_host(where, 0, &ap);
- if (!l)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to listen on %s", where);
- return -1;
- }
- if (cs_bind(l, ap, CS_SERVER) < 0)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where);
- cs_close (l);
- return -1;
- }
- if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
- EVENT_EXCEPT)))
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type");
- cs_close (l);
- return -1;
- }
- iochan_setdata(lst, l);
-
- /* Ensure our listener chain is setup properly */
- lst->next = pListener;
- pListener = lst;
- return 0; /* OK */
-}
-
-#ifndef WIN32
-/* UNIX only (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
-
-statserv_options_block *statserv_getcontrol(void)
-{
- static statserv_options_block cb;
-
- memcpy(&cb, &control_block, sizeof(cb));
- return &cb;
-}
-
-void statserv_setcontrol(statserv_options_block *block)
-{
- memcpy(&control_block, block, sizeof(*block));
-}
-
-static void statserv_reset(void)
-{
-}
-
-int statserv_start(int argc, char **argv)
-{
- int ret;
-
-#ifdef WIN32
- /* We need to initialize the thread list */
- ThreadList_Initialize();
-/* WIN32 */
-#endif
-
-#ifdef WIN32
- if ((me = strrchr (argv[0], '\\')))
- me++;
- else
- me = argv[0];
-#else
- me = argv[0];
-#endif
- if (control_block.options_func(argc, argv))
- return(1);
-
- if (control_block.bend_start)
- (*control_block.bend_start)(&control_block);
-#ifdef WIN32
- yaz_log (LOG_LOG, "Starting server %s", me);
-#else
-/* UNIX */
- if (control_block.inetd)
- inetd_connection(control_block.default_proto);
- else
- {
- yaz_log (LOG_LOG, "Starting server %s pid=%d", me, getpid());
-#if 0
- sigset_t sigs_to_block;
-
- sigemptyset(&sigs_to_block);
- sigaddset (&sigs_to_block, SIGTERM);
- pthread_sigmask (SIG_BLOCK, &sigs_to_block, 0);
- /* missing... */
-#endif
- if (control_block.dynamic)
- signal(SIGCHLD, catchchld);
- }
- signal (SIGPIPE, SIG_IGN);
- signal (SIGTERM, sigterm);
- if (*control_block.setuid)
- {
- struct passwd *pw;
-
- if (!(pw = getpwnam(control_block.setuid)))
- {
- yaz_log(LOG_FATAL, "%s: Unknown user", control_block.setuid);
- return(1);
- }
- if (setuid(pw->pw_uid) < 0)
- {
- yaz_log(LOG_FATAL|LOG_ERRNO, "setuid");
- exit(1);
- }
- }
-/* UNIX */
-#endif
-
-
- if ((pListener == NULL) && *control_block.default_listen)
- add_listener(control_block.default_listen,
- control_block.default_proto);
-
- if (pListener == NULL)
- ret = 1;
- else
- {
- yaz_log(LOG_LOG, "Entering event loop.");
- ret = event_loop(&pListener);
- }
- return ret;
-}
-
-int check_options(int argc, char **argv)
-{
- int ret = 0, r;
- char *arg;
-
- while ((ret = options("1a:iszSTl:v:u:c:w:t:k:d:D:", argv, argc, &arg)) != -2)
- {
- switch (ret)
- {
- case 0:
- if (add_listener(arg, control_block.default_proto))
- return 1; /* failed to create listener */
- break;
- case '1':
- control_block.one_shot = 1;
- control_block.dynamic = 0;
- break;
- case 'z':
- control_block.default_proto = PROTO_Z3950;
- break;
- case 's':
- fprintf (stderr, "%s: SR protocol no longer supported\n", me);
- exit (1);
- break;
- case 'S':
- control_block.dynamic = 0;
- break;
- case 'T':
-#if YAZ_POSIX_THREADS
- control_block.dynamic = 0;
- control_block.threads = 1;
-#elif YAZ_GNU_THREADS
- control_block.dynamic = 0;
- control_block.threads = 1;
-#else
- fprintf(stderr, "%s: Threaded mode not available.\n", me);
- return 1;
-#endif
- break;
- case 'l':
- strcpy(control_block.logfile, arg ? arg : "");
- yaz_log_init(control_block.loglevel, me, control_block.logfile);
- break;
- case 'v':
- control_block.loglevel = yaz_log_mask_str(arg);
- yaz_log_init(control_block.loglevel, me, control_block.logfile);
- break;
- case 'a':
- strcpy(control_block.apdufile, arg ? arg : "");
- break;
- case 'u':
- strcpy(control_block.setuid, arg ? arg : "");
- 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)))
- {
- fprintf(stderr, "%s: Specify positive timeout for -t.\n", me);
- return(1);
- }
- control_block.idle_timeout = r;
- break;
- case 'k':
- if (!arg || !(r = atoi(arg)))
- {
- fprintf(stderr, "%s: Specify positive size for -k.\n", me);
- return(1);
- }
- control_block.maxrecordsize = r * 1024;
- break;
- case 'i':
- control_block.inetd = 1;
- break;
- case 'w':
- if (chdir(arg))
- {
- perror(arg);
- return 1;
- }
- break;
- case 'D':
- max_sessions = atoi(arg);
- break;
- default:
- fprintf(stderr, "Usage: %s [ -a <pdufile> -v <loglevel>"
- " -l <logfile> -u <user> -c <config> -t <minutes>"
- " -k <kilobytes> -d <daemon>"
- " -ziST1 -w <directory> <listender-addr>... ]\n", me);
- return 1;
- }
- }
- return 0;
-}
-
-#ifdef WIN32
-typedef struct _Args
-{
- char **argv;
- int argc;
-} Args;
-
-static Args ArgDetails;
-
-/* name of the executable */
-#define SZAPPNAME "server"
-
-/* list of service dependencies - "dep1\0dep2\0\0" */
-#define SZDEPENDENCIES ""
-
-int statserv_main(int argc, char **argv,
- bend_initresult *(*bend_init)(bend_initrequest *r),
- void (*bend_close)(void *handle))
-{
- statserv_options_block *cb = statserv_getcontrol();
-
- cb->bend_init = bend_init;
- cb->bend_close = bend_close;
-
- statserv_setcontrol(cb);
-
- /* Lets setup the Arg structure */
- ArgDetails.argc = argc;
- ArgDetails.argv = argv;
-
- /* Now setup the service with the service controller */
- SetupService(argc, argv, &ArgDetails, SZAPPNAME,
- cb->service_name, /* internal service name */
- cb->service_display_name, /* displayed name */
- SZDEPENDENCIES);
- return 0;
-}
-
-int StartAppService(void *pHandle, int argc, char **argv)
-{
- /* Initializes the App */
- return 1;
-}
-
-void RunAppService(void *pHandle)
-{
- Args *pArgs = (Args *)pHandle;
-
- /* Starts the app running */
- statserv_start(pArgs->argc, pArgs->argv);
-}
-
-void StopAppService(void *pHandle)
-{
- /* Stops the app */
- statserv_closedown();
- statserv_reset();
-}
-/* WIN32 */
-#else
-/* UNIX */
-int statserv_main(int argc, char **argv,
- bend_initresult *(*bend_init)(bend_initrequest *r),
- void (*bend_close)(void *handle))
-{
- int ret;
- statserv_options_block *cb = statserv_getcontrol();
-
- cb->bend_init = bend_init;
- cb->bend_close = bend_close;
-
- statserv_setcontrol(cb);
- ret = statserv_start (argc, argv);
- statserv_closedown ();
- statserv_reset();
- return ret;
-}
-#endif