From 3cbcf01cfdb77d6d8d575c1b23ca6db6a039ffa8 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 3 Mar 2003 11:47:16 +0000 Subject: [PATCH] Added NT service support --- servers/slurpd/Makefile.in | 9 ++- servers/slurpd/args.c | 7 ++- servers/slurpd/fm.c | 22 ++++--- servers/slurpd/globals.c | 9 ++- servers/slurpd/globals.h | 2 + servers/slurpd/main.c | 117 ++++++++++++++++++++++++++++++----- servers/slurpd/nt_svc.c | 101 ++++++++++++++++++++++++++++++ servers/slurpd/proto-slurp.h | 1 + servers/slurpd/re.c | 4 +- servers/slurpd/slurp.h | 3 + 10 files changed, 245 insertions(+), 30 deletions(-) create mode 100644 servers/slurpd/nt_svc.c diff --git a/servers/slurpd/Makefile.in b/servers/slurpd/Makefile.in index b647edb2bd..b44f3b40ef 100644 --- a/servers/slurpd/Makefile.in +++ b/servers/slurpd/Makefile.in @@ -10,12 +10,17 @@ XPROGRAMS = sslurpd XSRCS = version.c +NT_SRCS = nt_svc.c +NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res + SRCS = admin.c args.c ch_malloc.c config.c \ fm.c globals.c ldap_op.c lock.c main.c re.c \ - reject.c replica.c replog.c ri.c rq.c sanity.c st.c + reject.c replica.c replog.c ri.c rq.c sanity.c st.c \ + $(@PLAT@_SRCS) OBJS = admin.o args.o ch_malloc.o config.o \ fm.o globals.o ldap_op.o lock.o main.o re.o \ - reject.o replica.o replog.o ri.o rq.o sanity.o st.o + reject.o replica.o replog.o ri.o rq.o sanity.o st.o \ + $(@PLAT@_OBJS) LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/servers/slurpd/args.c b/servers/slurpd/args.c index b7147ab22f..97dd2bd4df 100644 --- a/servers/slurpd/args.c +++ b/servers/slurpd/args.c @@ -44,6 +44,7 @@ usage( char *name ) #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ fprintf( stderr, "\t\t[-t tmp-dir] [-o]\n" ); #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ + fprintf( stderr, "\t\t[-n service-name]\n" ); } @@ -67,7 +68,7 @@ doargs( g->myname = strdup( g->myname + 1 ); } - while ( (i = getopt( argc, argv, "d:f:or:t:" )) != EOF ) { + while ( (i = getopt( argc, argv, "d:f:n:or:t:" )) != EOF ) { switch ( i ) { case 'd': /* set debug level and 'do not detach' flag */ g->no_detach = 1; @@ -109,6 +110,10 @@ doargs( case 'f': /* slapd config file */ g->slapd_configfile = strdup( optarg ); break; + case 'n': /* NT service name *. + if ( g->serverName ) free( g->serverName ); + g->serverName = strdup( optarg ); + break; case 'o': g->one_shot_mode = 1; break; diff --git a/servers/slurpd/fm.c b/servers/slurpd/fm.c index 6725a604aa..50740f25b5 100644 --- a/servers/slurpd/fm.c +++ b/servers/slurpd/fm.c @@ -36,7 +36,6 @@ */ static char *get_record LDAP_P(( FILE * )); static void populate_queue LDAP_P(( char *f )); -static RETSIGTYPE set_shutdown LDAP_P((int)); /* @@ -60,11 +59,14 @@ fm( * LDAP_SIGUSR2 - causes a shutdown */ (void) SIGNAL( LDAP_SIGUSR1, do_nothing ); - (void) SIGNAL( LDAP_SIGUSR2, set_shutdown ); - (void) SIGNAL( SIGTERM, set_shutdown ); - (void) SIGNAL( SIGINT, set_shutdown ); + (void) SIGNAL( LDAP_SIGUSR2, slurp_set_shutdown ); + (void) SIGNAL( SIGTERM, slurp_set_shutdown ); + (void) SIGNAL( SIGINT, slurp_set_shutdown ); #ifdef SIGHUP - (void) SIGNAL( SIGHUP, set_shutdown ); + (void) SIGNAL( SIGHUP, slurp_set_shutdown ); +#endif +#ifdef SIGBREAK + (void) SIGNAL( SIGBREAK, slurp_set_shutdown ); #endif if ( sglob->one_shot_mode ) { @@ -155,11 +157,15 @@ fm( /* * Set a global flag which signals that we're shutting down. */ -static RETSIGTYPE -set_shutdown(int sig) +RETSIGTYPE +slurp_set_shutdown(int sig) { int i; +#if HAVE_NT_SERVICE_MANAGER && SIGBREAK + if (sig == SIGBREAK) return do_nothing( sig ); +#endif + sglob->slurpd_shutdown = 1; /* set flag */ ldap_pvt_thread_kill( sglob->fm_tid, LDAP_SIGUSR1 ); /* wake up file mgr */ sglob->rq->rq_lock( sglob->rq ); /* lock queue */ @@ -168,7 +174,7 @@ set_shutdown(int sig) (sglob->replicas[ i ])->ri_wake( sglob->replicas[ i ]); } sglob->rq->rq_unlock( sglob->rq ); /* unlock queue */ - (void) SIGNAL_REINSTALL( sig, set_shutdown ); /* reinstall handlers */ + (void) SIGNAL_REINSTALL( sig, slurp_set_shutdown ); /* reinstall handlers */ } diff --git a/servers/slurpd/globals.c b/servers/slurpd/globals.c index 8a1cecbd52..5ff11118a0 100644 --- a/servers/slurpd/globals.c +++ b/servers/slurpd/globals.c @@ -39,7 +39,6 @@ int ldap_syslog_level = 0; #endif int ldap_debug = 0; - /* * Initialize the globals */ @@ -53,12 +52,17 @@ init_globals( void ) return NULL; } +#ifdef HAVE_NT_SERVICE_MANAGER + g->slapd_configfile = ".\\slapd.conf"; + g->slurpd_rdir = ".\\replica"; +#else g->slapd_configfile = SLAPD_DEFAULT_CONFIGFILE; + g->slurpd_rdir = DEFAULT_SLURPD_REPLICA_DIR "/replica"; +#endif g->no_work_interval = DEFAULT_NO_WORK_INTERVAL; g->slurpd_shutdown = 0; g->num_replicas = 0; g->replicas = NULL; - g->slurpd_rdir = DEFAULT_SLURPD_REPLICA_DIR "/replica"; strcpy( g->slurpd_status_file, DEFAULT_SLURPD_STATUS_FILE ); g->slapd_replogfile[ 0 ] = '\0'; g->slurpd_replogfile[ 0 ] = '\0'; @@ -66,6 +70,7 @@ init_globals( void ) g->one_shot_mode = 0; g->no_detach = 0; g->myname = NULL; + g->serverName = NULL; g->srpos = 0L; if ( St_init( &(g->st)) < 0 ) { fprintf( stderr, "Cannot initialize status data\n" ); diff --git a/servers/slurpd/globals.h b/servers/slurpd/globals.h index fbbca49591..7aba1c6727 100644 --- a/servers/slurpd/globals.h +++ b/servers/slurpd/globals.h @@ -53,6 +53,8 @@ typedef struct globals { int no_detach; /* Name of program */ char *myname; + /* NT service name */ + char *serverName; /* Current offset into slurpd replica logfile */ off_t srpos; /* mutex to serialize access to reject file */ diff --git a/servers/slurpd/main.c b/servers/slurpd/main.c index 3525146aed..3220853fb7 100644 --- a/servers/slurpd/main.c +++ b/servers/slurpd/main.c @@ -32,11 +32,24 @@ #include -int -main( - int argc, - char **argv -) +#ifdef HAVE_NT_SERVICE_MANAGER +#define MAIN_RETURN(x) return +#define SERVICE_EXIT( e, n ) do { \ + if ( is_NT_Service ) { \ + lutil_ServiceStatus.dwWin32ExitCode = (e); \ + lutil_ServiceStatus.dwServiceSpecificExitCode = (n); \ + } \ +} while ( 0 ) +#else +#define SERVICE_EXIT( e, n ) +#define MAIN_RETURN(x) return(x) +#endif + +#ifdef HAVE_NT_SERVICE_MANAGER +void WINAPI ServiceMain( DWORD argc, LPTSTR *argv ) +#else +int main( int argc, char **argv ) +#endif { #ifdef NO_THREADS /* Haven't yet written the non-threaded version */ @@ -44,7 +57,7 @@ main( return( 1 ); #else - int i; + int i, rc = 0; /* initialize thread package */ ldap_pvt_thread_initialize(); @@ -55,14 +68,60 @@ main( */ if (( sglob = init_globals()) == NULL ) { fprintf( stderr, "Out of memory initializing globals\n" ); - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_NOT_ENOUGH_MEMORY, 0 ); + rc = 1; + goto stop; } +#ifdef HAVE_NT_SERVICE_MANAGER + { + int *i; + char *newConfigFile; + char *regService = NULL; + + if ( is_NT_Service ) { + sglob->serverName = argv[0]; + lutil_CommenceStartupProcessing( sglob->serverName, slurp_set_shutdown ); + if ( strcmp(sglob->serverName, SERVICE_NAME) ) + regService = sglob->serverName; + } + + i = (int*)lutil_getRegParam( regService, "DebugLevel" ); + if ( i != NULL ) + { + ldap_debug = *i; +#ifdef NEW_LOGGING + lutil_log_initialize( argc, argv ); + LDAP_LOG( SLURPD, INFO, + "main: new debug level from registry is: %d\n", + ldap_debug, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", ldap_debug, 0, 0 ); +#endif + } + + newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" ); + if ( newConfigFile != NULL ) + { + sglob->slapd_configfile = newConfigFile; +#ifdef NEW_LOGGING + LDAP_LOG( SLURPD, INFO, + "main: new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 ); +#else + Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 ); +#endif + + } + } +#endif + /* * Process command-line args and fill in globals. */ if ( doargs( argc, argv, sglob ) < 0 ) { - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 ); + rc = 1; + goto stop; } /* @@ -72,13 +131,17 @@ main( fprintf( stderr, "Errors encountered while processing config file \"%s\"\n", sglob->slapd_configfile ); - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); + rc = 1; + goto stop; } #ifdef HAVE_TLS if( ldap_pvt_tls_init() || ldap_pvt_tls_init_def_ctx() ) { fprintf( stderr, "TLS Initialization failed.\n" ); - exit( EXIT_FAILURE); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); + rc = 1; + goto stop; } #endif @@ -87,7 +150,9 @@ main( */ if ( mkdir(sglob->slurpd_rdir, 0755) == -1 && errno != EEXIST) { perror(sglob->slurpd_rdir); - exit( 1 ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 ); + rc = 1; + goto stop; } /* @@ -96,7 +161,9 @@ main( if ( sglob->st->st_read( sglob->st )) { fprintf( stderr, "Malformed slurpd status file \"%s\"\n", sglob->slurpd_status_file, 0, 0 ); - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 17 ); + rc = 1; + goto stop; } /* @@ -104,7 +171,9 @@ main( * Check for any fatal error conditions before we get started */ if ( sanity() < 0 ) { - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 ); + rc = 1; + goto stop; } /* @@ -116,6 +185,10 @@ main( lutil_detach( 0, 0 ); #endif +#ifdef HAVE_NT_EVENT_LOG + if (is_NT_Service) lutil_LogStartedEvent( sglob->serverName, ldap_debug, sglob->slapd_configfile, "n/a" ); +#endif + /* * Start the main file manager thread (in fm.c). */ @@ -129,7 +202,9 @@ main( Debug( LDAP_DEBUG_ANY, "file manager ldap_pvt_thread_create failed\n", 0, 0, 0 ); #endif - exit( EXIT_FAILURE ); + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 ); + rc = 1; + goto stop; } @@ -147,6 +222,10 @@ main( start_replica_thread( sglob->replicas[ i ]); } +#ifdef HAVE_NT_SERVICE_MANAGER + if ( started_event ) ldap_pvt_thread_cond_signal( &started_event ); +#endif + /* * Wait for the fm thread to finish. */ @@ -161,6 +240,14 @@ main( ldap_pvt_thread_join( sglob->replicas[ i ]->ri_tid, (void *) NULL ); } +stop: +#ifdef HAVE_NT_SERVICE_MANAGER + if (is_NT_Service) { + ldap_pvt_thread_cond_destroy( &started_event ); + lutil_LogStoppedEvent( sglob->serverName ); + lutil_ReportShutdownComplete(); + } +#endif /* destroy the thread package */ ldap_pvt_thread_destroy(); @@ -169,6 +256,6 @@ main( #else Debug( LDAP_DEBUG_ANY, "slurpd: terminated.\n", 0, 0, 0 ); #endif - return 0; + MAIN_RETURN(rc); #endif /* !NO_THREADS */ } diff --git a/servers/slurpd/nt_svc.c b/servers/slurpd/nt_svc.c new file mode 100644 index 0000000000..9be6d49db8 --- /dev/null +++ b/servers/slurpd/nt_svc.c @@ -0,0 +1,101 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" +#include +#include +#include +#include "slurp.h" +#include "lutil.h" + +#ifdef HAVE_NT_SERVICE_MANAGER + +/* in main.c */ +void WINAPI ServiceMain( DWORD argc, LPTSTR *argv ); + +int main( int argc, LPTSTR *argv ) +{ + int length; + char filename[MAX_PATH], *fname_start; + + /* + * Because the service was registered as SERVICE_WIN32_OWN_PROCESS, + * the lpServiceName element of the SERVICE_TABLE_ENTRY will be + * ignored. + */ + + SERVICE_TABLE_ENTRY DispatchTable[] = { + { "", (LPSERVICE_MAIN_FUNCTION) ServiceMain }, + { NULL, NULL } + }; + + /* + * set the service's current directory to the installation directory + * for the service. this way we don't have to write absolute paths + * in the configuration files + */ + GetModuleFileName( NULL, filename, sizeof( filename ) ); + fname_start = strrchr( filename, *LDAP_DIRSEP ); + + if ( argc > 1 ) { + if ( _stricmp( "install", argv[1] ) == 0 ) + { + char *svcName = SERVICE_NAME; + char *displayName = "OpenLDAP Replication Service"; + BOOL auto_start = FALSE; + + if ( (argc > 2) && (argv[2] != NULL) ) + svcName = argv[2]; + + if ( argc > 3 && argv[3]) + displayName = argv[3]; + + if ( argc > 4 && stricmp(argv[4], "auto") == 0) + auto_start = TRUE; + + strcat(filename, " service"); + if ( !lutil_srv_install(svcName, displayName, filename, auto_start) ) + { + fputs( "service failed installation ...\n", stderr ); + return EXIT_FAILURE; + } + fputs( "service has been installed ...\n", stderr ); + return EXIT_SUCCESS; + } + + if ( _stricmp( "remove", argv[1] ) == 0 ) + { + char *svcName = SERVICE_NAME; + if ( (argc > 2) && (argv[2] != NULL) ) + svcName = argv[2]; + if ( !lutil_srv_remove(svcName, filename) ) + { + fputs( "failed to remove the service ...\n", stderr ); + return EXIT_FAILURE; + } + fputs( "service has been removed ...\n", stderr ); + return EXIT_SUCCESS; + } + if ( _stricmp( "service", argv[1] ) == 0 ) + { + is_NT_Service = 1; + *fname_start = '\0'; + SetCurrentDirectory( filename ); + } + } + + if (is_NT_Service) + { + StartServiceCtrlDispatcher(DispatchTable); + } else + { + ServiceMain( argc, argv ); + } + + return EXIT_SUCCESS; +} + +#endif diff --git a/servers/slurpd/proto-slurp.h b/servers/slurpd/proto-slurp.h index 5fec1060d1..bdcce9ad68 100644 --- a/servers/slurpd/proto-slurp.h +++ b/servers/slurpd/proto-slurp.h @@ -38,6 +38,7 @@ void ch_free LDAP_P(( void *p )); /* fm.c */ void *fm LDAP_P((void *arg)); RETSIGTYPE do_nothing LDAP_P((int i)); +RETSIGTYPE slurp_set_shutdown LDAP_P((int)); /* globals.c */ extern struct globals *sglob; diff --git a/servers/slurpd/re.c b/servers/slurpd/re.c index 1100396a87..f063c39f96 100644 --- a/servers/slurpd/re.c +++ b/servers/slurpd/re.c @@ -33,11 +33,11 @@ #include #include +#include "../slapd/slap.h" + #include "slurp.h" #include "globals.h" -#include "../slapd/slap.h" - /* Forward references */ static Rh *get_repl_hosts LDAP_P(( char *, int *, char ** )); static int gettype LDAP_P(( char * )); diff --git a/servers/slurpd/slurp.h b/servers/slurpd/slurp.h index 63afb0792a..43f310dc62 100644 --- a/servers/slurpd/slurp.h +++ b/servers/slurpd/slurp.h @@ -49,6 +49,9 @@ #define S_IWGRP 0 #endif +#undef SERVICE_NAME +#define SERVICE_NAME OPENLDAP_PACKAGE "-slurpd" + /* Default directory for slurpd's private copy of replication logs */ #define DEFAULT_SLURPD_REPLICA_DIR LDAP_RUNDIR LDAP_DIRSEP "openldap-slurp" -- 2.39.5