--- /dev/null
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2008 Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Index Data nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file sc.h
+ * \brief Header for Windows Service Control stuff
+ */
+
+
+#include <yaz/yconfig.h>
+
+YAZ_BEGIN_CDECL
+
+typedef struct sc_s *yaz_sc_t;
+
+YAZ_EXPORT yaz_sc_t yaz_sc_create(const char *service_name,
+ const char *display_name);
+
+YAZ_EXPORT void yaz_sc_running(yaz_sc_t s);
+
+YAZ_EXPORT 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));
+
+YAZ_EXPORT void yaz_sc_destroy(yaz_sc_t *s);
+
+YAZ_END_CDECL
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2008 Index Data
+ * See the file LICENSE for details.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <tchar.h>
+#include <direct.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <yaz/xmalloc.h>
+#include <yaz/log.h>
+#include <yaz/sc.h>
+#include <yaz/wrbuf.h>
+
+struct sc_s {
+ int install_flag;
+ int start_flag;
+ int remove_flag;
+ int run_flag;
+ char *service_name;
+ char *display_name;
+ int (*sc_main)(yaz_sc_t s, int argc, char **argv);
+ void (*sc_stop)(yaz_sc_t s);
+ SERVICE_STATUS_HANDLE gSvcStatusHandle;
+ SERVICE_STATUS gSvcStatus;
+};
+
+
+yaz_sc_t yaz_sc_create(const char *service_name, const char *display_name)
+{
+ yaz_sc_t s = xmalloc(sizeof(*s));
+
+ s->service_name = xstrdup(service_name);
+ s->display_name = xstrdup(display_name);
+ s->install_flag = 0;
+ s->start_flag = 0;
+ s->remove_flag = 0;
+ s->run_flag = 0;
+ s->sc_main = 0;
+ s->sc_stop = 0;
+ s->gSvcStatusHandle = 0;
+ return s;
+}
+
+static void parse_args(yaz_sc_t s, int *argc_p, char ***argv_p)
+{
+ int skip_opt = 0;
+ const char *log_file = 0;
+ int i;
+
+ /* now look for the service arguments */
+ skip_opt = 0;
+ for (i = 1; i < *argc_p; i++)
+ {
+ const char *opt = (*argv_p)[i];
+ if (!strcmp(opt, "-install"))
+ {
+ s->install_flag = 1;
+ skip_opt = 1;
+ break;
+ }
+ else if (!strcmp(opt, "-installa"))
+ {
+ s->install_flag = 1;
+ s->start_flag = 1;
+ skip_opt = 1;
+ break;
+ }
+ else if (!strcmp(opt, "-remove"))
+ {
+ s->remove_flag = 1;
+ skip_opt = 1;
+ break;
+ }
+ else if (!strcmp(opt, "-run") && i < *argc_p-1)
+ {
+ /* -run dir */
+ const char *dir = (*argv_p)[i+1];
+ s->run_flag = 1;
+ chdir(dir);\r
+ skip_opt = 2;
+ break;
+ }
+ }
+ *argc_p -= skip_opt;
+ for (; i < *argc_p; i++)
+ (*argv_p)[i] = (*argv_p)[i + skip_opt];
+
+ /* we must have a YAZ log file to work with */
+ for (i = 1; i < *argc_p; i++)
+ {
+ const char *opt = (*argv_p)[i];
+ if (opt[0] == '-' && opt[1] == 'l')
+ {
+ if (opt[2])
+ {
+ log_file = opt+2;
+ skip_opt = 1;
+ break;
+ }
+ else if (i < *argc_p - 1)
+ {
+ log_file = (*argv_p)[i+1];
+ skip_opt = 2;
+ break;
+ }
+ }
+ }
+ if (log_file)
+ yaz_log_init_file(log_file);
+ else
+ {
+ if (s->install_flag)
+ {
+ yaz_log(YLOG_FATAL, "Must specify -l logfile for service to install");
+ exit(1);
+ }
+ }
+ if (s->run_flag)
+ { /* remove -l logfile for a running service */
+ for (; i < *argc_p; i++)
+ (*argv_p)[i] = (*argv_p)[i + skip_opt];
+ }
+}
+
+VOID sc_ReportSvcStatus(yaz_sc_t s,
+ DWORD dwCurrentState,
+ DWORD dwWin32ExitCode,
+ DWORD dwWaitHint)
+{
+ if (s->gSvcStatusHandle)
+ {
+ static DWORD dwCheckPoint = 1;
+
+ // Fill in the SERVICE_STATUS structure.
+
+ s->gSvcStatus.dwCurrentState = dwCurrentState;
+ s->gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
+ s->gSvcStatus.dwWaitHint = dwWaitHint;
+
+ if (dwCurrentState == SERVICE_START_PENDING)
+ s->gSvcStatus.dwControlsAccepted = 0;
+ else
+ s->gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+ if ( (dwCurrentState == SERVICE_RUNNING) ||
+ (dwCurrentState == SERVICE_STOPPED) )
+ s->gSvcStatus.dwCheckPoint = 0;
+ else
+ s->gSvcStatus.dwCheckPoint = dwCheckPoint++;
+
+ // Report the status of the service to the SCM.
+ SetServiceStatus(s->gSvcStatusHandle, &s->gSvcStatus );
+ }
+}
+
+static yaz_sc_t global_sc = 0;
+
+VOID WINAPI sc_SvcCtrlHandler(DWORD dwCtrl)
+{
+ switch(dwCtrl)
+ {
+ case SERVICE_CONTROL_STOP:
+ yaz_log(YLOG_LOG, "Service %s to stop", global_sc->service_name);
+ sc_ReportSvcStatus(global_sc, SERVICE_STOP_PENDING, NO_ERROR, 0);
+ global_sc->sc_stop(global_sc);
+ sc_ReportSvcStatus(global_sc, SERVICE_STOPPED, NO_ERROR, 0);
+ return;
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+ default:
+ break;
+ }
+}
+
+static void WINAPI sc_service_main(DWORD argc, char **argv)
+{
+ yaz_sc_t s = global_sc;
+ int ret_code;
+
+ yaz_log(YLOG_LOG, "Service %s starting", s->service_name);
+
+ s->gSvcStatusHandle = RegisterServiceCtrlHandler(
+ s->service_name, sc_SvcCtrlHandler);
+
+ if (!s->gSvcStatusHandle)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "RegisterServiceCtrlHandler");
+ return;
+ }
+
+ s->gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ s->gSvcStatus.dwServiceSpecificExitCode = 0;
+
+ sc_ReportSvcStatus(s, SERVICE_START_PENDING, NO_ERROR, 3000);
+
+ ret_code = s->sc_main(s, argc, argv);
+
+ sc_ReportSvcStatus(s, SERVICE_STOPPED,
+ ret_code ? ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR, ret_code);
+}
+
+void yaz_sc_running(yaz_sc_t s)
+{
+ sc_ReportSvcStatus(s, SERVICE_RUNNING, NO_ERROR, 0);
+}
+
+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))
+
+{
+ s->sc_main = sc_main;
+ s->sc_stop = sc_stop;
+ parse_args(s, &argc, &argv);
+
+ if (s->install_flag || s->remove_flag)
+ {
+ SC_HANDLE manager = OpenSCManager(NULL /* machine */,
+ NULL /* database */,
+ SC_MANAGER_ALL_ACCESS);
+ if (manager == NULL)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "OpenSCManager failed");
+ exit(1);
+ }
+ if (s->install_flag)
+ {
+ SC_HANDLE schService = 0;
+ TCHAR szPath[2048];
+ int i;
+ WRBUF w = wrbuf_alloc();
+ char cwdstr[_MAX_PATH];
+
+ if (!_getcwd(cwdstr, sizeof(cwdstr)))
+ strcpy (cwdstr, ".");
+
+ if (GetModuleFileName(NULL, szPath, 2048) == 0)
+ {
+ yaz_log(YLOG_FATAL, "GetModuleFileName failed");
+ exit(1);
+ }
+ wrbuf_puts(w, szPath);
+ for (i = 1; i < argc; i++)
+ {
+ wrbuf_puts(w, " ");
+ wrbuf_puts(w, argv[i]);
+ }
+ wrbuf_puts(w, " -run \"");
+ wrbuf_puts(w, cwdstr);
+ wrbuf_puts(w, "\"");
+ yaz_log(YLOG_LOG, "path: %s", wrbuf_cstr(w));
+
+ schService =
+ CreateService(
+ manager, /* SCM database */
+ TEXT(s->service_name), /* name of service */
+ TEXT(s->display_name), /* service name to display */
+ SERVICE_ALL_ACCESS, /* desired access */
+ SERVICE_WIN32_OWN_PROCESS, /* service type */
+ s->start_flag ?
+ SERVICE_AUTO_START : SERVICE_DEMAND_START, /* start type */
+ SERVICE_ERROR_NORMAL, /* error control type */
+ wrbuf_cstr(w), /* path to service's binary */
+ NULL, /* no load ordering group */
+ NULL, /* no tag identifier */
+ NULL, /* no dependencies */
+ NULL, /* LocalSystem account */
+ NULL); /* no password */
+ if (schService == NULL)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be installed",
+ s->service_name);
+ CloseServiceHandle(manager);
+ exit(1);
+ }
+ yaz_log(YLOG_LOG, "Installed service %s", s->service_name);
+ CloseServiceHandle(schService);
+ wrbuf_destroy(w);
+ }
+ else if (s->remove_flag)
+ {
+ SC_HANDLE schService = 0;
+ SERVICE_STATUS serviceStatus;
+
+ schService = OpenService(manager, TEXT(s->service_name), SERVICE_ALL_ACCESS);
+ if (schService == NULL)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be opened",
+ s->service_name);
+ CloseServiceHandle(manager);
+ exit(1);
+ }
+ /* try to stop the service */
+ if (ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus))
+ {
+ yaz_log(YLOG_LOG, "Service %s being stopped", s->service_name);
+ Sleep(1000);
+ while (QueryServiceStatus(schService, &serviceStatus))
+ {
+ if (serviceStatus.dwCurrentState != SERVICE_STOP_PENDING)
+ break;
+ Sleep( 1000 );
+ }
+ if (serviceStatus.dwCurrentState != SERVICE_STOPPED)
+ yaz_log(YLOG_LOG|YLOG_FATAL, "Service failed to stop");
+ }
+ if (DeleteService(schService))
+ yaz_log(YLOG_LOG, "Service %s removed", s->service_name);
+ else
+ yaz_log(YLOG_FATAL, "Service %s could not be removed", s->service_name);
+ CloseServiceHandle(schService);
+ }
+ CloseServiceHandle(manager);
+ exit(0);
+ }
+ global_sc = s;
+ if (s->run_flag)
+ {
+ SERVICE_TABLE_ENTRY dt[2];
+
+ dt[0].lpServiceName = s->service_name;
+ dt[0].lpServiceProc = sc_service_main;
+ dt[1].lpServiceName = 0;
+ dt[1].lpServiceProc = 0;
+
+ if (!StartServiceCtrlDispatcher(dt))
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be controlled",
+ s->service_name);
+ }
+ }
+ else
+ {
+ /* run the program standalone (with no service) */
+ return s->sc_main(s, argc, argv);
+ }
+ return 0;
+}
+
+void yaz_sc_destroy(yaz_sc_t *s)
+{
+ xfree((*s)->service_name);
+ xfree((*s)->display_name);
+ xfree(*s);
+ *s = 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2008 Index Data
+ * See the file LICENSE for details.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <tchar.h>
+#include <direct.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <yaz/xmalloc.h>
+#include <yaz/log.h>
+#include <yaz/sc.h>
+
+HANDLE default_stop_event = NULL;
+static void default_sc_stop(yaz_sc_t s)
+{
+ SetEvent(default_stop_event);
+}
+
+static int default_sc_main(yaz_sc_t s, int argc, char **argv)
+{
+ default_stop_event = CreateEvent(
+ NULL, // default security attributes
+ TRUE, // manual reset event
+ FALSE, // not signaled
+ NULL); // no name
+
+ if (default_stop_event == NULL)
+ {
+ return 1;
+ }
+ yaz_sc_running(s);
+ WaitForSingleObject(default_stop_event, INFINITE);
+ return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+ yaz_sc_t s = yaz_sc_create("yaz_sc_test", "YAZ Service Control Test");
+
+ yaz_sc_program(s, argc, argv, default_sc_main, default_sc_stop);
+
+ yaz_sc_destroy(&s);
+ exit(0);
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
+++ /dev/null
-/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2008 Index Data
- * See the file LICENSE for details.
- */
-
-/**
- * \file service.c
- * \brief Implements NT service handling for GFS.
- */
-
-#ifdef WIN32
-
-#include <windows.h>
-#include <stdio.h>
-#include <tchar.h>
-#include <direct.h>
-
-#include "service.h"
-
-static AppService *pService = NULL;
-static BOOL bRunAsService = TRUE;
-static void *pAppHandle = NULL;
-
-/* Private functions to this module */
-void Service_Create(LPTSTR pAppName, LPTSTR pServiceName, LPTSTR pServiceDisplayName, LPTSTR pDependancies, int argc, char **argv);
-void Service_Delete();
-void Service_Initialize();
-BOOL NotifyServiceController();
-BOOL UpdateServiceStatus(DWORD Status);
-void FailServiceStart(DWORD Win32Code, DWORD PrivateCode);
-void CmdInstallService(int argc, char *argv[], BOOL bAutoStart);
-void CmdRemoveService();
-LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize);
-BOOL CheckServiceArguments(int argc, char *argv[]);
-
-/* Callback functions for thee service manager */
-void WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
-void WINAPI ServiceControlHandler(DWORD fdwControl);
-
-/* Function to handle Ctrl + C etc... */
-BOOL EventHandlerRoutine(DWORD dwCtrlType);
-
-void Service_Create(LPTSTR pAppName, LPTSTR pServiceName, LPTSTR pServiceDisplayName, LPTSTR pDependancies, int argc, char **argv)
-{
- pService = malloc(sizeof(AppService));
- pService->pAppName = pAppName;
- pService->pServiceName = pServiceName;
- pService->pServiceDisplayName = pServiceDisplayName;
- pService->pDependancies = pDependancies;
- pService->hService = 0;
- pService->ServiceTable[0].lpServiceName = pServiceName;
- pService->ServiceTable[0].lpServiceProc = ServiceMain;
- pService->ServiceTable[1].lpServiceName = NULL;
- pService->ServiceTable[1].lpServiceProc = NULL;
- pService->argc = argc;
- pService->argv = argv;
-}
-
-void Service_Delete()
-{
- if (pService != NULL)
- {
- /* Mark the service as stopping */
- UpdateServiceStatus(SERVICE_STOP_PENDING);
-
- /* Stop the service */
- StopAppService(pAppHandle);
-
- /* Service has now stopped */
- UpdateServiceStatus(SERVICE_STOPPED);
-
- /* Free the memory */
- free(pService);
- pService = NULL;
- }
-}
-
-void Service_Initialize()
-{
- if (pService != NULL)
- {
- /* Register ourselves with the control dispatcher */
- StartServiceCtrlDispatcher(pService->ServiceTable);
- }
-}
-
-void WINAPI ServiceMain(DWORD argc, LPTSTR argv[])
-{
- if (pService != NULL)
- {
- if (NotifyServiceController())
- {
- /* Set the status to pending */
- UpdateServiceStatus(SERVICE_START_PENDING);
-
- /* Lets attempt to start the service */
- if (StartAppService(pAppHandle, pService->argc, pService->argv))
- {
- /* Service is now up and running */
- UpdateServiceStatus(SERVICE_RUNNING);
-
- /* Lets wait for our clients */
- RunAppService(pAppHandle);
- }
- else
- {
- FailServiceStart(GetLastError(), 0);
- Service_Delete();
- }
- }
- }
-}
-
-BOOL NotifyServiceController()
-{
- if (pService == NULL)
- {
- return(FALSE);
- }
- else
- {
- if (bRunAsService)
- {
- pService->ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- pService->ServiceStatus.dwCurrentState = SERVICE_STOPPED;
- pService->ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- pService->ServiceStatus.dwWin32ExitCode = 0;
- pService->ServiceStatus.dwServiceSpecificExitCode = 0;
- pService->ServiceStatus.dwCheckPoint = 0;
- pService->ServiceStatus.dwWaitHint = 0;
- pService->hService = RegisterServiceCtrlHandler(pService->pServiceName, ServiceControlHandler);
-
- if (pService->hService)
- UpdateServiceStatus(SERVICE_START_PENDING);
- else
- return(FALSE);
- }
- return(TRUE);
- }
-}
-
-void WINAPI ServiceControlHandler(DWORD fdwControl)
-{
- if (pService != NULL)
- {
- switch (fdwControl)
- {
- case SERVICE_CONTROL_STOP:
- /* Update the service status to be pending */
- Service_Delete();
- break;
-
- case SERVICE_CONTROL_INTERROGATE:
- UpdateServiceStatus(pService->ServiceStatus.dwCurrentState);
- break;
-
- default:
- break;
- }
- }
-}
-
-BOOL UpdateServiceStatus(DWORD Status)
-{
- if (pService != NULL)
- {
- if (pService->hService)
- {
- pService->ServiceStatus.dwCurrentState = Status;
- if ((Status == SERVICE_START_PENDING) || (Status == SERVICE_STOP_PENDING))
- {
- pService->ServiceStatus.dwCheckPoint ++;
- pService->ServiceStatus.dwWaitHint = 5000; /* 5 sec.*/
- }
- else
- {
- pService->ServiceStatus.dwCheckPoint = 0;
- pService->ServiceStatus.dwWaitHint = 0;
- }
-
- return(SetServiceStatus(pService->hService, &pService->ServiceStatus));
- }
- }
-
- return(FALSE);
-}
-
-void FailServiceStart(DWORD Win32Code, DWORD PrivateCode)
-{
- if (pService != NULL)
- {
- pService->ServiceStatus.dwWin32ExitCode = Win32Code;
- pService->ServiceStatus.dwServiceSpecificExitCode = PrivateCode;
- UpdateServiceStatus(SERVICE_STOPPED);
- }
-}
-
-void CmdInstallService(int argc, char *argv[], BOOL bAutoStart)
-{
- if (pService != NULL)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- TCHAR szPath[2048];
-
- if (GetModuleFileName(NULL, szPath, 512) == 0)
- {
- _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(pService->pServiceDisplayName), GetLastErrorText(pService->szErr, 256));
- }
- else
- {
- int i;
- char cwdstr[_MAX_PATH];
-
- if (!_getcwd(cwdstr, sizeof(cwdstr)))
- strcpy (cwdstr, ".");
-
- strcat (szPath, TEXT(" -runservice \""));
- strcat (szPath, cwdstr);
- strcat (szPath, "\"");
-
- for (i = 1; i < argc; i++)
- {
- /* We will add the given command line arguments to the command */
- /* We are not interested in the install and remove options */
- if ((strcmp("-install", argv[i]) != 0) &&
- (strcmp("-installa", argv[i]) != 0) &&
- (strcmp("-remove", argv[i]) != 0))
- {
- strcat(szPath, TEXT(" "));
- strcat(szPath, argv[i]);
- }
- }
-
- schSCManager = OpenSCManager(NULL, /* machine (NULL == local) */
- NULL, /* database (NULL == default) */
- SC_MANAGER_ALL_ACCESS); /* access required */
- if (schSCManager)
- {
- schService = CreateService(schSCManager, /* SCManager database */
- TEXT(pService->pServiceName), /* name of service */
- TEXT(pService->pServiceDisplayName), /* name to display */
- SERVICE_ALL_ACCESS, /* desired access */
- SERVICE_WIN32_OWN_PROCESS, /* service type */
- bAutoStart ? SERVICE_AUTO_START :
- SERVICE_DEMAND_START, /* start type */
- SERVICE_ERROR_NORMAL, /* error control type */
- szPath, /* service's binary */
- NULL, /* no load ordering group */
- NULL, /* no tag identifier */
- TEXT(pService->pDependancies), /* dependencies */
- NULL, /* LocalSystem account */
- NULL); /* no password */
-
- if (schService)
- {
- _tprintf(TEXT("%s installed.\n"), TEXT(pService->pServiceDisplayName));
- CloseServiceHandle(schService);
- }
- else
- {
- _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(pService->szErr, 256));
- }
-
- CloseServiceHandle(schSCManager);
- }
- else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(pService->szErr,256));
- }
- }
-}
-
-void CmdRemoveService()
-{
- if (pService != NULL)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- schSCManager = OpenSCManager(NULL, /* machine (NULL == local) */
- NULL, /* database (NULL == default) */
- SC_MANAGER_ALL_ACCESS); /* access required */
- if (schSCManager)
- {
- schService = OpenService(schSCManager, TEXT(pService->pServiceName), SERVICE_ALL_ACCESS);
-
- if (schService)
- {
- /* try to stop the service */
- if (ControlService(schService, SERVICE_CONTROL_STOP, &pService->ServiceStatus))
- {
- _tprintf(TEXT("Stopping %s."), TEXT(pService->pServiceDisplayName));
- Sleep(1000);
-
- while (QueryServiceStatus(schService, &pService->ServiceStatus))
- {
- if (pService->ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
- {
- _tprintf(TEXT("."));
- Sleep( 1000 );
- }
- else
- break;
- }
-
- if (pService->ServiceStatus.dwCurrentState == SERVICE_STOPPED)
- _tprintf(TEXT("\n%s stopped.\n"), TEXT(pService->pServiceDisplayName));
- else
- _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(pService->pServiceDisplayName));
-
- }
-
- /* now remove the service */
- if(DeleteService(schService))
- _tprintf(TEXT("%s removed.\n"), TEXT(pService->pServiceDisplayName));
- else
- _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(pService->szErr,256));
-
- CloseServiceHandle(schService);
- }
- else
- _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(pService->szErr,256));
-
- CloseServiceHandle(schSCManager);
- }
- else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(pService->szErr,256));
- }
-}
-
-LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
-{
- DWORD dwRet;
- LPTSTR lpszTemp = NULL;
-
- dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL,
- GetLastError(),
- LANG_NEUTRAL,
- (LPTSTR)&lpszTemp,
- 0,
- NULL);
-
- /* supplied buffer is not long enough */
- if (!dwRet || ((long)dwSize < (long)dwRet + 14))
- lpszBuf[0] = TEXT('\0');
- else
- {
- lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); /* remove cr and newline character */
- _stprintf(lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError());
- }
-
- if (lpszTemp)
- LocalFree((HLOCAL)lpszTemp);
-
- return(lpszBuf);
-}
-
-BOOL CheckServiceArguments(int argc, char *argv[])
-{
- int i;
-
- /* Lets process the arguments */
- for (i = 1; i < argc; i++)
- {
- if (stricmp("-install", argv[i]) == 0)
- {
- /* They want to install the service */
- CmdInstallService(argc, argv, FALSE);
-
- /* We don't carry on, after we have installed the service */
- return(FALSE);
- }
- else if (stricmp("-installa", argv[i]) == 0)
- {
- /* They want to install the service */
- CmdInstallService(argc, argv, TRUE);
-
- /* We don't carry on, after we have installed the service */
- return(FALSE);
- }
- else if (stricmp("-remove", argv[i]) == 0)
- {
- /* Here they want to remove it */
- CmdRemoveService();
-
- /* We don't carry on, after we have removed the service */
- return(FALSE);
- }
- else if (stricmp ("-runservice", argv[i]) == 0)
- {
- /* We can carry on, if we reached here */
- chdir(argv[i+1]);
- argv[i] = "";
- argv[i+1] = "";
- return(TRUE);
- }
- }
- bRunAsService = FALSE;
- return(TRUE);
-}
-
-BOOL SetupService(int argc, char *argv[], void *pHandle, LPTSTR pAppName, LPTSTR pServiceName, LPTSTR pServiceDisplayName, LPTSTR pDependancies)
-{
- BOOL bDeleteService = TRUE;
- BOOL bResult = FALSE;
-
- /* Save the handle for later use */
- pAppHandle = pHandle;
-
- /* Create our service class */
- Service_Create(pAppName, pServiceName, pServiceDisplayName, pDependancies, argc, argv);
-
- if (CheckServiceArguments(argc, argv))
- {
- if (bRunAsService)
- {
- /* No need to set the console control handler, as the service manager handles all this for us */
- Service_Initialize();
- bDeleteService = FALSE;
- }
- else
- {
- /* Set the console control handler for exiting the program */
- SetConsoleCtrlHandler((PHANDLER_ROUTINE)EventHandlerRoutine, TRUE);
-
- /* Now do the main work */
- ServiceMain(argc, argv);
- }
-
- /* We have been successful initializing, so let the caller know */
- bResult = TRUE;
- }
-
- if (bDeleteService)
- {
- /* Finished with the service now */
- Service_Delete();
- }
- return(bResult);
-}
-
-BOOL EventHandlerRoutine(DWORD dwCtrlType)
-{
- /* This routine dosn't seem to get called all the time, Why ??? */
- switch (dwCtrlType)
- {
- case CTRL_C_EVENT: /* A CTRL+C signal was received, either from keyboard input or from a signal generated by the GenerateConsoleCtrlEvent function.*/
- case CTRL_BREAK_EVENT: /* A CTRL+BREAK signal was received, either from keyboard input or from a signal generated by GenerateConsoleCtrlEvent.*/
- case CTRL_CLOSE_EVENT: /* A signal that the system sends to all processes attached to a console when the user closes the console (either by choosing the Close command from the console window's System menu, or by choosing the End Task command from the Task List).*/
- case CTRL_LOGOFF_EVENT: /* A signal that the system sends to all console processes when a user is logging off. This signal does not indicate which user is logging off, so no assumptions can be made.*/
- case CTRL_SHUTDOWN_EVENT: /* A signal that the system sends to all console processes when the system */
- /* We are basically shutting down, so call Service_Delete */
- Service_Delete();
- return(FALSE);
- break;
-
- default:
- /* we are not handling this one, so return FALSE */
- return(FALSE);
- }
-}
-#endif
-/*
- * Local variables:
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- * vim: shiftwidth=4 tabstop=8 expandtab
- */
-
+++ /dev/null
-/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2008 Index Data.
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Index Data nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * \file service.h
- * \brief Header for NT service handling.
- */
-
-#ifndef SERVICE_INCLUDED
-#define SERVICE_INCLUDED
-
-#ifdef WIN32
-
-#include <windows.h>
-
-typedef struct _Service
-{
- LPTSTR pAppName;
- LPTSTR pServiceName;
- LPTSTR pServiceDisplayName;
- LPTSTR pDependancies;
- TCHAR szErr[256];
- SERVICE_STATUS_HANDLE hService;
- SERVICE_STATUS ServiceStatus;
- SERVICE_TABLE_ENTRY ServiceTable[2];
- int argc;
- char **argv;
-} AppService;
-
-/* Called by the app to initialize the service */
-BOOL SetupService(int argc, char *argv[], void *pHandle, LPTSTR pAppName, LPTSTR pServiceName, LPTSTR pServiceDisplayName, LPTSTR pDependancies);
-
-#endif /* WIN32 */
-
-/* Functions that must be in the main application */
-/* Initializes the app */
-int StartAppService(void *pHandle, int argc, char **argv);
-
-/* Now we wait for any connections */
-void RunAppService(void *pHandle);
-
-/* Time to tidyup and stop the service */
-void StopAppService(void *pHandle);
-
-#endif
-/*
- * Local variables:
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- * vim: shiftwidth=4 tabstop=8 expandtab
- */
-
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+
#ifdef WIN32
#include <process.h>
#include <winsock.h>
#include <direct.h>
-#include "service.h"
#endif
+
+#include <yaz/sc.h>
+
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
if (!strcmp((const char *) ptr->name, "host"))
{
gfs->host = nmem_dup_xml_content(gfs_nmem,
- ptr->children);
+ ptr->children);
}
else if (!strcmp((const char *) ptr->name, "config"))
{
/* Initialize the critical Sections */
InitializeCriticalSection(&Thread_CritSect);
- /* Set the first thraed */
+ /* Set the first thraed */
pFirstThread = NULL;
/* we have been initialized */
return -1;
}
if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
- EVENT_EXCEPT, listen_id)))
+ EVENT_EXCEPT, listen_id)))
{
yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create IOCHAN-type");
cs_close (l);
fprintf(stderr, "Usage: %s [ -a <pdufile> -v <loglevel>"
" -l <logfile> -u <user> -c <config> -t <minutes>"
" -k <kilobytes> -d <daemon> -p <pidfile> -C certfile"
- " -ziDST1 -m <time-format> -w <directory> <listener-addr>... ]\n", me);
+ " -ziDST1 -m <time-format> -w <directory> <listener-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))
+void statserv_sc_stop(yaz_sc_t s)
{
- struct statserv_options_block *cb = &control_block;
- cb->bend_init = bend_init;
- cb->bend_close = bend_close;
-
- /* 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;
+ statserv_closedown();
+ statserv_reset();
}
-void RunAppService(void *pHandle)
+int statserv_sc_main(yaz_sc_t s, int argc, char **argv)
{
- Args *pArgs = (Args *)pHandle;
-
- /* Starts the app running */
- statserv_start(pArgs->argc, pArgs->argv);
+ yaz_sc_running(s);
+ return statserv_start(argc, 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;
+ struct statserv_options_block *cb = &control_block;
- control_block.bend_init = bend_init;
- control_block.bend_close = bend_close;
+ yaz_sc_t s = yaz_sc_create(cb->service_name,
+ cb->service_display_name);
- ret = statserv_start (argc, argv);
- statserv_closedown ();
- statserv_reset();
+ cb->bend_init = bend_init;
+ cb->bend_close = bend_close;
+
+ ret = yaz_sc_program(s, argc, argv, statserv_sc_main, statserv_sc_stop);
+ yaz_sc_destroy(&s);
return ret;
}
-#endif
+
/*
* Local variables:
* c-basic-offset: 4
default: all
-all: dirs generate dll client ztest yazicu zoomsh utilprog testprog iconv icu libxml2 libxslt
+all: dirs generate dll sc_test client ztest yazicu zoomsh utilprog testprog iconv icu libxml2 libxslt
NSIS="c:\program files\nsis\makensis.exe"
HHC="c:\program files\html help workshop\hhc.exe"
YAZ_ICU=$(BINDIR)\yaz-icu.exe
ZOOMSH=$(BINDIR)\zoomsh.exe
ZTEST=$(BINDIR)\yaz-ztest.exe
+SC_TEST=$(BINDIR)\sc_test.exe
ZOOMTST1=$(BINDIR)\zoomtst1.exe
ZOOMTST2=$(BINDIR)\zoomtst2.exe
client: dirs generate $(CLIENT)
ztest: dirs generate $(ZTEST)
+sc_test: $(SC_TEST)
+
zoomsh: $(ZOOMSH) $(ZOOMTST1) $(ZOOMTST2) $(ZOOMTST3) \
$(ZOOMTST4) $(ZOOMTST5) $(ZOOMTST6) $(ZOOMTST7) $(ZOOMTST8) $(ZOOMTST9) \
$(ZOOMTST10)
$(OBJDIR)\read-grs.obj \
$(OBJDIR)\ztest.obj
+SC_TEST_OBJS = \
+ $(OBJDIR)\sc_test.obj
+
YAZ_ZOOMSH_OBJS = \
$(OBJDIR)\zoomsh.obj
$(OBJDIR)\oid_std.obj \
$(OBJDIR)\eventl.obj \
$(OBJDIR)\requestq.obj \
- $(OBJDIR)\service.obj \
$(OBJDIR)\seshigh.obj \
$(OBJDIR)\statserv.obj \
$(OBJDIR)\tcpdchk.obj \
$(OBJDIR)\iconv_encode_iso_8859_1.obj \
$(OBJDIR)\iconv_encode_marc8.obj \
$(OBJDIR)\iconv_decode_marc8.obj \
- $(OBJDIR)\iconv_encode_wchar.obj
+ $(OBJDIR)\iconv_encode_wchar.obj \
+ $(OBJDIR)\sc.obj
Z3950_OBJS= \
$(OBJDIR)\z-date.obj\
$(MT) -manifest $@.manifest -outputresource:$@;1
+$(SC_TEST) : "$(BINDIR)" $(SC_TEST_OBJS) $(YAZ_DLL)
+ $(LINK_PROGRAM) $(SC_TEST_OBJS) /out:$@
+ $(MT) -manifest $@.manifest -outputresource:$@;1
+
$(ZOOMSH) : "$(BINDIR)" $(YAZ_ZOOMSH_OBJS) $(YAZ_DLL)
$(LINK_PROGRAM) $(YAZ_ZOOMSH_OBJS) /out:$@
$(MT) -manifest $@.manifest -outputresource:$@;1