X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fsc.c;h=f3931178036e4aa88b5ffe2c6bbcf7bcd2f56a5e;hp=7102fa8683845cbdbff1760d6c44e8d5211737a5;hb=4f411c0f26882f2a4e91010ae901815b2bb245dc;hpb=540056f9cf1a3304b253db09eba899cc6763466d diff --git a/src/sc.c b/src/sc.c index 7102fa8..f393117 100644 --- a/src/sc.c +++ b/src/sc.c @@ -1,7 +1,14 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2008 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ +/** + * \file sc.c + * \brief Windows Service Control + */ +#if HAVE_CONFIG_H +#include +#endif #ifdef WIN32 #include @@ -25,27 +32,34 @@ struct sc_s { char *display_name; int (*sc_main)(yaz_sc_t s, int argc, char **argv); void (*sc_stop)(yaz_sc_t s); + int argc; + char **argv; +#ifdef WIN32 SERVICE_STATUS_HANDLE gSvcStatusHandle; SERVICE_STATUS gSvcStatus; +#endif }; yaz_sc_t yaz_sc_create(const char *service_name, const char *display_name) { - yaz_sc_t s = xmalloc(sizeof(*s)); + yaz_sc_t s = (yaz_sc_t) xmalloc(sizeof(*s)); - s->service_name = xstrdup(service_name); - s->display_name = xstrdup(display_name); + s->service_name = service_name ? xstrdup(service_name) : 0; + s->display_name = display_name ? xstrdup(display_name) : 0; s->install_flag = 0; s->start_flag = 0; s->remove_flag = 0; s->run_flag = 0; s->sc_main = 0; s->sc_stop = 0; +#ifdef WIN32 s->gSvcStatusHandle = 0; +#endif return s; } +#ifdef WIN32 static void parse_args(yaz_sc_t s, int *argc_p, char ***argv_p) { int skip_opt = 0; @@ -81,16 +95,18 @@ static void parse_args(yaz_sc_t s, int *argc_p, char ***argv_p) /* -run dir */ const char *dir = (*argv_p)[i+1]; s->run_flag = 1; - chdir(dir); - skip_opt = 2; - break; + chdir(dir); + skip_opt = 2; + break; } } - *argc_p -= skip_opt; + *argc_p = *argc_p - skip_opt; for (; i < *argc_p; i++) (*argv_p)[i] = (*argv_p)[i + skip_opt]; + /* now look for the service arguments */ /* we must have a YAZ log file to work with */ + skip_opt = 0; for (i = 1; i < *argc_p; i++) { const char *opt = (*argv_p)[i]; @@ -122,12 +138,14 @@ static void parse_args(yaz_sc_t s, int *argc_p, char ***argv_p) } if (s->run_flag) { /* remove -l logfile for a running service */ + *argc_p = *argc_p - skip_opt; for (; i < *argc_p; i++) (*argv_p)[i] = (*argv_p)[i + skip_opt]; + } } -VOID sc_ReportSvcStatus(yaz_sc_t s, +VOID sc_ReportSvcStatus(yaz_sc_t s, DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) @@ -144,13 +162,13 @@ VOID sc_ReportSvcStatus(yaz_sc_t s, if (dwCurrentState == SERVICE_START_PENDING) s->gSvcStatus.dwControlsAccepted = 0; - else + else s->gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; if ( (dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED) ) s->gSvcStatus.dwCheckPoint = 0; - else + else s->gSvcStatus.dwCheckPoint = dwCheckPoint++; // Report the status of the service to the SCM. @@ -160,19 +178,19 @@ VOID sc_ReportSvcStatus(yaz_sc_t s, static yaz_sc_t global_sc = 0; -VOID WINAPI sc_SvcCtrlHandler(DWORD dwCtrl) +VOID WINAPI sc_SvcCtrlHandler(DWORD dwCtrl) { - switch(dwCtrl) - { - case SERVICE_CONTROL_STOP: + 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: + case SERVICE_CONTROL_INTERROGATE: + break; + default: break; } } @@ -184,29 +202,32 @@ static void WINAPI sc_service_main(DWORD argc, char **argv) yaz_log(YLOG_LOG, "Service %s starting", s->service_name); - s->gSvcStatusHandle = RegisterServiceCtrlHandler( + s->gSvcStatusHandle = RegisterServiceCtrlHandler( s->service_name, sc_SvcCtrlHandler); if (!s->gSvcStatusHandle) - { + { yaz_log(YLOG_FATAL|YLOG_ERRNO, "RegisterServiceCtrlHandler"); - return; - } + return; + } - s->gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - s->gSvcStatus.dwServiceSpecificExitCode = 0; + 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); - + ret_code = s->sc_main(s, s->argc, s->argv); + sc_ReportSvcStatus(s, SERVICE_STOPPED, ret_code ? ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR, ret_code); } +#endif void yaz_sc_running(yaz_sc_t s) { +#ifdef WIN32 sc_ReportSvcStatus(s, SERVICE_RUNNING, NO_ERROR, 0); +#endif } int yaz_sc_program(yaz_sc_t s, int argc, char **argv, @@ -216,6 +237,7 @@ int yaz_sc_program(yaz_sc_t s, int argc, char **argv, { s->sc_main = sc_main; s->sc_stop = sc_stop; +#ifdef WIN32 parse_args(s, &argc, &argv); if (s->install_flag || s->remove_flag) @@ -248,15 +270,19 @@ int yaz_sc_program(yaz_sc_t s, int argc, char **argv, for (i = 1; i < argc; i++) { wrbuf_puts(w, " "); + if (strchr(argv[i], ' ')) + wrbuf_puts(w, "\""); wrbuf_puts(w, argv[i]); + if (strchr(argv[i], ' ')) + wrbuf_puts(w, "\""); } wrbuf_puts(w, " -run \""); wrbuf_puts(w, cwdstr); wrbuf_puts(w, "\""); yaz_log(YLOG_LOG, "path: %s", wrbuf_cstr(w)); - schService = - CreateService( + schService = + CreateService( manager, /* SCM database */ TEXT(s->service_name), /* name of service */ TEXT(s->display_name), /* service name to display */ @@ -271,7 +297,7 @@ int yaz_sc_program(yaz_sc_t s, int argc, char **argv, NULL, /* no dependencies */ NULL, /* LocalSystem account */ NULL); /* no password */ - if (schService == NULL) + if (schService == NULL) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be installed", s->service_name); @@ -286,9 +312,9 @@ int yaz_sc_program(yaz_sc_t s, int argc, char **argv, { SC_HANDLE schService = 0; SERVICE_STATUS serviceStatus; - + schService = OpenService(manager, TEXT(s->service_name), SERVICE_ALL_ACCESS); - if (schService == NULL) + if (schService == NULL) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be opened", s->service_name); @@ -328,18 +354,18 @@ int yaz_sc_program(yaz_sc_t s, int argc, char **argv, dt[1].lpServiceName = 0; dt[1].lpServiceProc = 0; + s->argc = argc; + s->argv = argv; if (!StartServiceCtrlDispatcher(dt)) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "Service %s could not be controlled", s->service_name); } + return 0; } - else - { - /* run the program standalone (with no service) */ - return s->sc_main(s, argc, argv); - } - return 0; +#endif /* WIN32 */ + /* run the program standalone (with no service) */ + return s->sc_main(s, argc, argv); } void yaz_sc_destroy(yaz_sc_t *s) @@ -353,6 +379,7 @@ void yaz_sc_destroy(yaz_sc_t *s) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab