From 4d13d4071a3e5183ed32301e4f5eabc1db733b03 Mon Sep 17 00:00:00 2001 From: Gary Williams Date: Wed, 16 Jun 1999 19:15:35 +0000 Subject: [PATCH] add code to support slapd as NT service --- servers/slapd/daemon.c | 87 +++++++++++++++++-------- servers/slapd/main.c | 141 ++++++++++++++++++++++++++++++++++------- 2 files changed, 181 insertions(+), 47 deletions(-) diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 932e36babf..abb0053ddd 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -1,4 +1,5 @@ #include "portable.h" +//#include "portable_err.h" #include @@ -22,18 +23,22 @@ int deny_severity = LOG_NOTICE; /* globals */ int dtblsize; +static int tcps; #ifdef HAVE_WINSOCK2 +// in nt_main.c +extern ldap_pvt_thread_cond_t started_event; /* forward reference */ void hit_socket(); /* In wsa_err.c */ char *WSAGetLastErrorString(); +static ldap_pvt_thread_t hit_tid; #define WAKE_LISTENER(w) \ do {\ if( w ) {\ ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\ - hit_socket();\ + hit_socket(); \ }\ } while(0) #else @@ -45,9 +50,13 @@ do {\ } while(0) #endif +#ifndef HAVE_WINSOCK +static +#endif +volatile sig_atomic_t slapd_shutdown = 0; + static int daemon_initialized = 0; static ldap_pvt_thread_t listener_tid; -static volatile sig_atomic_t slapd_shutdown = 0; static volatile sig_atomic_t slapd_listener = 0; void sockinit(); @@ -119,17 +128,24 @@ void slapd_clr_write(int s, int wake) { FD_CLR( (unsigned) s, &slap_daemon.sd_writers ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + + if( wake ) { + ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 ); + } } void slapd_set_write(int s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); - assert( FD_ISSET( s, &slap_daemon.sd_actives) ); FD_SET( (unsigned) s, &slap_daemon.sd_writers ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + + if( wake ) { + ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 ); + } } void slapd_clr_read(int s, int wake) { @@ -141,6 +157,9 @@ void slapd_clr_read(int s, int wake) { ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + if( wake ) { + ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 ); + } } void slapd_set_read(int s, int wake) { @@ -151,6 +170,10 @@ void slapd_set_read(int s, int wake) { FD_SET( (unsigned) s, &slap_daemon.sd_readers ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + + if( wake ) { + ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 ); + } } static void slapd_close(int s) { @@ -158,6 +181,8 @@ static void slapd_close(int s) { tcp_close(s); } + + int set_socket( struct sockaddr_in *addr ) { @@ -252,10 +277,12 @@ slapd_daemon_task( void *ptr ) { - int inetd = ((int *)ptr) [0]; - int tcps = ((int *)ptr) [1]; + struct sockaddr_in *slapd_addr = (struct sockaddr_in*)((int *)ptr)[0]; + int inetd; + tcps = ((int *)ptr) [1]; free( ptr ); + inetd = ( slapd_addr == NULL); if ( !daemon_initialized ) sockinit(); slapd_listener=1; @@ -289,6 +316,11 @@ slapd_daemon_task( slapd_add( 0 ); } +#ifdef HAVE_WINSOCK + if ( started_event != NULL ) + ldap_pvt_thread_cond_signal( &started_event ); +#endif + // initialization complete. Here comes the loop. while ( !slapd_shutdown ) { unsigned int i; int ns, nfds; @@ -302,7 +334,7 @@ slapd_daemon_task( #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD) struct hostent *hp; #endif - struct timeval zero; + struct timeval zero; struct timeval *tvp; char *client_name; @@ -357,7 +389,11 @@ slapd_daemon_task( switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) { case -1: { /* failure - try again */ +#ifdef HAVE_WINSOCK + int err = WSAGetLastError(); +#else int err = errno; +#endif if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) { continue; @@ -371,7 +407,8 @@ slapd_daemon_task( ? sys_errlist[err] : "unknown", 0 ); - slapd_shutdown = -1; + + slapd_shutdown = -1; } } continue; @@ -481,7 +518,6 @@ slapd_daemon_task( } #endif /* HAVE_TCPD */ - if( (id = connection_init(s, client_name, client_addr)) < 0 ) { Debug( LDAP_DEBUG_ANY, "daemon: connection_init(%d, %s, %s) failed.\n", @@ -534,7 +570,7 @@ slapd_daemon_task( for ( i = 0; i < nfds; i++ ) #endif { - int wd, active; + int wd; #ifdef HAVE_WINSOCK wd = writefds.fd_array[i]; @@ -548,7 +584,6 @@ slapd_daemon_task( if ( wd == tcps ) { continue; } - Debug( LDAP_DEBUG_CONNS, "daemon: write active on %d\n", wd, 0, 0 ); @@ -572,7 +607,7 @@ slapd_daemon_task( for ( i = 0; i < nfds; i++ ) #endif { - int rd, active; + int rd; #ifdef HAVE_WINSOCK rd = readfds.fd_array[i]; @@ -590,7 +625,6 @@ slapd_daemon_task( Debug ( LDAP_DEBUG_CONNS, "daemon: read activity on %d\n", rd, 0, 0 ); - /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. @@ -607,13 +641,13 @@ slapd_daemon_task( if( slapd_shutdown > 0 ) { Debug( LDAP_DEBUG_TRACE, - "daemon: shutdown requested (%d) and initiated.\n", - (int) slapd_shutdown, 0, 0 ); + "daemon: shutdown requested and initiated.\n", + 0, 0, 0 ); } else if ( slapd_shutdown < 0 ) { Debug( LDAP_DEBUG_TRACE, - "daemon: abnormal condition (%d), shutdown initiated.\n", - (int) slapd_shutdown, 0, 0 ); + "daemon: abnormal condition, shutdown initiated.\n", + 0, 0, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "daemon: no active streams, shutdown initiated.\n", @@ -624,9 +658,6 @@ slapd_daemon_task( slapd_close( tcps ); } - /* we only implement "quick" shutdown */ - connections_shutdown(); - ldap_pvt_thread_mutex_lock( &active_threads_mutex ); Debug( LDAP_DEBUG_ANY, "slapd shutdown: waiting for %d threads to terminate\n", @@ -636,10 +667,10 @@ slapd_daemon_task( } ldap_pvt_thread_mutex_unlock( &active_threads_mutex ); - slapd_listener = 0; return NULL; } + int slapd_daemon( int inetd, int tcps ) { int rc; @@ -717,25 +748,27 @@ void sockinit() daemon_initialized = 1; } /* The WinSock DLL is acceptable. Proceed. */ -void hit_socket( void ) +void hit_socket() { int s, on = 1; extern struct sockaddr_in bind_addr; /* throw something at the socket to terminate the select() in the daemon thread. */ if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET ) - Debug( LDAP_DEBUG_TRACE, + Debug( LDAP_DEBUG_ANY, "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n", WSAGetLastError(), WSAGetLastErrorString(), 0 ); if ( ioctlsocket( s, FIONBIO, &on ) == -1 ) - Debug( LDAP_DEBUG_TRACE, + Debug( LDAP_DEBUG_ANY, "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n", s, WSAGetLastError(), WSAGetLastError() ); - + bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) { + Debug( LDAP_DEBUG_ANY, + "hit_socket: error on connect: %d\n", WSAGetLastError(), 0 ); /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */ } @@ -767,7 +800,11 @@ slap_set_shutdown( int sig ) ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 ); } #else - hit_socket(); + Debug( LDAP_DEBUG_TRACE, "Shutdown %d ordered", sig, 0 ); + // trying to "hit" the socket seems to always get a + // EWOULDBLOCK error, so just close the listen socket to + // break out of the select since we're shutting down anyway + tcp_close( tcps ); #endif /* reinstall self */ (void) SIGNAL( sig, slap_set_shutdown ); diff --git a/servers/slapd/main.c b/servers/slapd/main.c index e1e85ac113..c999033db3 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -13,12 +13,44 @@ #include "ldapconfig.h" #include "slap.h" +#ifndef HAVE_WINSOCK #include "lutil.h" /* Get lutil_detach() */ +#endif #ifdef LDAP_SIGCHLD static RETSIGTYPE wait4child( int sig ); #endif +#ifdef HAVE_WINSOCK +#define SERVICE_NAME "OpenLDAP" + +struct sockaddr_in bind_addr; + +// in nt_main.c +extern SERVICE_STATUS SLAPDServiceStatus; +extern SERVICE_STATUS_HANDLE hSLAPDServiceStatus; +extern ldap_pvt_thread_cond_t started_event, stopped_event; +extern int is_NT_Service; + +void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short port, int udp ); +void LogSlapdStoppedEvent( char *svc ); + +void CommenceStartupProcessing( LPCTSTR serviceName, + void(*stopper)(int)); +void ReportSlapdShutdownComplete( void ); +void *getRegParam( char *svc, char *value ); + +#define SERVICE_EXIT( e, n ) \ + if ( is_NT_Service ) \ +{ \ + SLAPDServiceStatus.dwWin32ExitCode = e; \ + SLAPDServiceStatus.dwServiceSpecificExitCode = n; \ +} +#else +#define SERVICE_EXIT( e, n ) +#endif + +short port = LDAP_PORT; /* * when more than one slapd is running on one machine, each one might have * it's own LOCAL for syslogging and must have its own pid/args files @@ -62,7 +94,7 @@ static void usage( char *name ) { fprintf( stderr, "usage: %s [-d ?|debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]", name ); - fprintf( stderr, "\n [-a bind-address] [-i]" ); + fprintf( stderr, "\n [-a bind-address] [-i] [-u]" ); #if LDAP_CONNECTIONLESS fprintf( stderr, " [-c]" ); #endif @@ -80,39 +112,73 @@ usage( char *name ) time_t starttime; struct sockaddr_in bind_addr; +int tcps; -int -main( int argc, char **argv ) +#ifdef HAVE_WINSOCK +void WINAPI ServiceMain( DWORD argc, LPTSTR *argv ) { +#else +void main( int argc, char **argv ) +{ +#endif + int i; int inetd = 0; int rc; - int tcps; -#ifdef LDAP_CONNECTIONLESS + struct sockaddr_in *slapd_addr; int udp; -#endif #ifdef LOG_LOCAL4 int syslogUser = DEFAULT_SYSLOG_USER; #endif -#if defined(HAVE_SETUID) && defined(HAVE_SETGID) - char *username = NULL, *groupname = NULL; +#ifdef HAVE_WINSOCK + char *configfile = ".\\slapd.conf"; +#else + char *configfile = SLAPD_DEFAULT_CONFIGFILE; #endif - char *configfile; char *serverName; int serverMode = SLAP_SERVER_MODE; - configfile = SLAPD_DEFAULT_CONFIGFILE; - (void) memset( (void*) &bind_addr, '\0', sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); - bind_addr.sin_port = htons(LDAP_PORT); + bind_addr.sin_port = htons(port); g_argc = argc; g_argv = argv; +#ifdef HAVE_WINSOCK + //if ( is_NT_Service ) + { + int *newPort; + int *newDebugLevel; + char *newConfigFile; + ldap_debug = 0xffff; + if ( is_NT_Service ) CommenceStartupProcessing( SERVICE_NAME, slap_set_shutdown ); + newPort = (int*)getRegParam( NULL, "Port" ); + if ( newPort != NULL ) + { + port = *newPort; + bind_addr.sin_port = htons(port); + Debug ( LDAP_DEBUG_ANY, "new port from registry is: %d\n", port, 0, 0 ); + } + newDebugLevel = (int*)getRegParam( NULL, "DebugLevel" ); + if ( newDebugLevel != NULL ) + { + slap_debug = *newDebugLevel; + Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", slap_debug, 0, 0 ); + } + newConfigFile = (char*)getRegParam( NULL, "ConfigFile" ); + if ( newConfigFile != NULL ) + { + configfile = newConfigFile; + Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 ); + } + } + +#endif + while ( (i = getopt( argc, argv, - "d:f:ia:p:s:" + "d:f:ia:p:s:u" #ifdef LOG_LOCAL4 "l:" #endif @@ -189,7 +255,7 @@ main( int argc, char **argv ) break; case 'p': { /* port on which to listen */ - short port = (short)atoi( optarg ); + port = (short)atoi( optarg ); if(! port ) { fprintf(stderr, "-p %s must be numeric\n", optarg); } else { @@ -234,7 +300,9 @@ main( int argc, char **argv ) default: usage( argv[0] ); - exit( 1 ); + rc = 1; + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 ); + goto stop; } } @@ -256,8 +324,6 @@ main( int argc, char **argv ) openlog( serverName, OPENLOG_OPTIONS ); #endif - tcps = set_socket( inetd ? NULL : &bind_addr ); - #if defined(HAVE_SETUID) && defined(HAVE_SETGID) if ( username != NULL || groupname != NULL ) slap_init_user( username, groupname ); @@ -265,14 +331,19 @@ main( int argc, char **argv ) if ( slap_init( serverMode, serverName ) != 0 ) { rc = 1; + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 ); goto destroy; } if ( read_config( configfile ) != 0 ) { rc = 1; + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); goto destroy; } + + tcps = set_socket( inetd ? NULL : &bind_addr ); + (void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing ); (void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown ); #ifdef SIGPIPE @@ -286,8 +357,12 @@ main( int argc, char **argv ) #ifdef LDAP_SIGCHLD (void) SIGNAL( LDAP_SIGCHLD, wait4child ); #endif +#ifdef HAVE_WINSOCK + // SIGBREAK is generated when Ctrl-Break is pressed. + (void) SIGNAL( SIGBREAK, slap_set_shutdown ); +#endif -#ifndef WIN32 +#ifndef HAVE_WINSOCK if(!inetd) { #ifdef LDAP_DEBUG lutil_detach( ldap_debug, 0 ); @@ -295,16 +370,19 @@ main( int argc, char **argv ) lutil_detach( 0, 0 ); #endif } -#endif /* WIN32 */ +#endif /* HAVE_WINSOC */ if ( slap_startup(-1) != 0 ) { rc = 1; + SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); goto shutdown; } if(!inetd) { FILE *fp; + slapd_addr = &bind_addr; + Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 ); if (( slapd_pid_file != NULL ) && @@ -323,11 +401,23 @@ main( int argc, char **argv ) fprintf( fp, "\n" ); fclose( fp ); } + + } else { + slapd_addr = NULL; } time( &starttime ); +#ifdef HAVE_WINSOCK + LogSlapdStartedEvent( SERVICE_NAME, slap_debug, configfile, port, udp ); +#endif + rc = slapd_daemon( slapd_addr, tcps ); + +#ifdef HAVE_WINSOCK + // Throw away the event that we used during the startup process. + if ( is_NT_Service ) + ldap_pvt_thread_cond_destroy( &started_event ); +#endif - rc = slapd_daemon( inetd, tcps ); shutdown: /* remember an error during shutdown */ @@ -336,11 +426,18 @@ destroy: /* remember an error during destroy */ rc |= slap_destroy(); +stop: +#ifdef HAVE_WINSOCK + LogSlapdStoppedEvent( SERVICE_NAME ); +#endif Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 ); +#ifdef HAVE_WINSOCK + ReportSlapdShutdownComplete(); +#endif - closelog(); + closelog(); - return rc; + return; } -- 2.39.5