]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
ldap_pvt_thread_kill doesn't work on NT, so use hit_socket to break select. Also...
[openldap] / servers / slapd / daemon.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/ctype.h>
6 #include <ac/errno.h>
7 #include <ac/signal.h>
8 #include <ac/socket.h>
9 #include <ac/string.h>
10 #include <ac/time.h>
11 #include <ac/unistd.h>
12
13 #include "ldapconfig.h"
14 #include "slap.h"
15
16 #ifdef HAVE_TCPD
17 #include <tcpd.h>
18
19 int allow_severity = LOG_INFO;
20 int deny_severity = LOG_NOTICE;
21 #endif /* TCP Wrappers */
22
23 /* globals */
24 int dtblsize;
25
26 #ifdef HAVE_WINSOCK2
27 /* forward reference */
28 void hit_socket();
29 /* In wsa_err.c */
30 char *WSAGetLastErrorString();
31
32 #define WAKE_LISTENER \
33     if( wake ) {\
34         ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
35         hit_socket();\
36     }
37 #else
38 #define WAKE_LISTENER \
39     if( wake ) {\
40         ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
41     }
42 #endif
43
44 static int daemon_initialized = 0;
45 static ldap_pvt_thread_t        listener_tid;
46 static volatile sig_atomic_t slapd_shutdown = 0;
47 static volatile sig_atomic_t slapd_listener = 0;
48 void sockinit();
49
50 struct slap_daemon {
51         ldap_pvt_thread_mutex_t sd_mutex;
52
53         int sd_nactives;
54
55 #ifndef HAVE_WINSOCK
56         /* In winsock, accept() returns values higher than dtblsize
57                 so don't bother with this optimization */
58         int sd_nfds;
59 #endif
60
61         fd_set sd_actives;
62         fd_set sd_readers;
63         fd_set sd_writers;
64 } slap_daemon; 
65
66 /*
67  * Add a descriptor to daemon control
68  */
69 static void slapd_add(int s) {
70         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
71
72         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
73         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
74         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
75
76 #ifndef HAVE_WINSOCK
77         if (s >= slap_daemon.sd_nfds) {
78                 slap_daemon.sd_nfds = s + 1;
79         }
80 #endif
81
82         FD_SET( s, &slap_daemon.sd_actives );
83         FD_SET( s, &slap_daemon.sd_readers );
84
85         Debug( LDAP_DEBUG_CONNS, "daemon: added %d%s%s\n", s,
86             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
87                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
88
89         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
90 }
91
92 /*
93  * Remove the descriptor from daemon control
94  */
95 void slapd_remove(int s) {
96         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
97
98         assert( FD_ISSET( s, &slap_daemon.sd_actives ));
99
100         Debug( LDAP_DEBUG_CONNS, "daemon: removing %d%s%s\n", s,
101             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
102                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
103
104         FD_CLR( s, &slap_daemon.sd_actives );
105         FD_CLR( s, &slap_daemon.sd_readers );
106         FD_CLR( s, &slap_daemon.sd_writers );
107
108         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
109 }
110
111 void slapd_clr_write(int s, int wake) {
112         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
113
114         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
115         FD_CLR( s, &slap_daemon.sd_writers );
116
117         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
118
119         WAKE_LISTENER;
120 }
121
122 void slapd_set_write(int s, int wake) {
123         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
124
125         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
126         FD_SET( s, &slap_daemon.sd_writers );
127
128         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
129
130     WAKE_LISTENER;
131 }
132
133 void slapd_clr_read(int s, int wake) {
134         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
135
136         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
137         FD_CLR( s, &slap_daemon.sd_readers );
138
139         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
140
141     WAKE_LISTENER;
142 }
143
144 void slapd_set_read(int s, int wake) {
145         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
146
147         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
148         FD_SET( s, &slap_daemon.sd_readers );
149
150         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
151
152     WAKE_LISTENER;
153 }
154
155 static void slapd_close(int s) {
156         slapd_remove(s);
157
158         Debug( LDAP_DEBUG_CONNS, "daemon: closing %d\n", s, 0, 0 );
159         tcp_close(s);
160 }
161
162 int
163 set_socket( struct sockaddr_in *addr )
164 {
165         int     tcps = -1;
166     if ( !daemon_initialized ) sockinit();
167
168 #ifdef HAVE_SYSCONF
169         dtblsize = sysconf( _SC_OPEN_MAX );
170 #elif HAVE_GETDTABLESIZE
171         dtblsize = getdtablesize();
172 #else
173         dtblsize = FD_SETSIZE;
174 #endif
175
176 #ifdef FD_SETSIZE
177         if(dtblsize > FD_SETSIZE) {
178                 dtblsize = FD_SETSIZE;
179         }
180 #endif  /* !FD_SETSIZE */
181
182         if( addr != NULL ) {
183                 int     tmp;
184
185                 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
186 #ifndef WIN32
187                         int err = errno;
188                         Debug( LDAP_DEBUG_ANY,
189                                 "daemon: socket() failed errno %d (%s)\n", err,
190                         err > -1 && err < sys_nerr ? sys_errlist[err] :
191                         "unknown", 0 );
192 #endif
193 #ifdef WIN32
194                         Debug( LDAP_DEBUG_ANY, 
195                                 "daemon: socket() failed errno %d (%s)\n", WSAGetLastError(),
196                         WSAGetLastErrorString(), 0 );
197 #endif
198                         exit( 1 );
199                 }
200
201 #ifndef HAVE_WINSOCK
202                 if ( tcps >= dtblsize ) {
203                         Debug( LDAP_DEBUG_ANY,
204                                 "daemon: listener descriptor %d is too great\n",
205                                 tcps, dtblsize, 0 );
206                         exit( 1 );
207                 }
208 #endif
209
210                 tmp = 1;
211                 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
212                         (char *) &tmp, sizeof(tmp) ) == -1 )
213                 {
214                         int err = errno;
215                         Debug( LDAP_DEBUG_ANY,
216                                "slapd(%d): setsockopt() failed errno %d (%s)\n",
217                         tcps, err,
218                                 err > -1 && err < sys_nerr
219                                         ? sys_errlist[err] : "unknown" );
220                 }
221
222                 if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
223                         int err = errno;
224                         Debug( LDAP_DEBUG_ANY, "daemon: bind(%d) failed errno %d (%s)\n",
225                         tcps, err,
226                                 err > -1 && err < sys_nerr
227                                         ? sys_errlist[err] : "unknown" );
228                         exit( 1 );
229                 }
230         }
231
232         return tcps;
233 }
234
235 static void *
236 slapd_daemon_task(
237         void *ptr
238 )
239 {
240         int inetd = ((int *)ptr) [0];
241         int tcps  = ((int *)ptr) [1];
242         free( ptr );
243
244     if ( !daemon_initialized ) sockinit();
245
246         slapd_listener=1;
247
248         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
249         FD_ZERO( &slap_daemon.sd_readers );
250         FD_ZERO( &slap_daemon.sd_writers );
251
252         if( !inetd ) {
253                 if ( listen( tcps, 5 ) == -1 ) {
254                         int err = errno;
255                         Debug( LDAP_DEBUG_ANY,
256                                 "daemon: listen(%d, 5) failed errno %d (%s)\n",
257                             tcps, err,
258                                 err > -1 && err < sys_nerr
259                                         ? sys_errlist[err] : "unknown" );
260                         exit( 1 );
261                 }
262
263                 slapd_add( tcps );
264
265         } else {
266                 if( connection_init( 0, NULL, NULL ) ) {
267                         Debug( LDAP_DEBUG_ANY,
268                                 "connection_init(%d) failed.\n",
269                                 0, 0, 0 );
270
271                         exit( 1 );
272                 }
273
274                 slapd_add( 0 );
275         }
276
277         while ( !slapd_shutdown ) {
278                 unsigned int i;
279                 int ns, nfds;
280
281                 fd_set                  readfds;
282                 fd_set                  writefds;
283
284                 struct sockaddr_in      from;
285 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
286         struct hostent          *hp;
287 #endif
288         struct timeval          zero;
289                 struct timeval          *tvp;
290
291                 char    *client_name;
292                 char    *client_addr;
293
294                 FD_ZERO( &writefds );
295                 FD_ZERO( &readfds );
296
297                 zero.tv_sec = 0;
298                 zero.tv_usec = 0;
299
300                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
301
302 #ifdef FD_SET_MANUAL_COPY
303                 for( s = 0; s < nfds; s++ ) {
304                         if(FD_ISSET( &slap_sd_writers, s )) {
305                                 FD_SET( &writefds, s );
306                         }
307                         if(FD_ISSET( &slap_sd_writers, s )) {
308                                 FD_SET( &writefds, s );
309                         }
310                 }
311 #else
312                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
313                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
314 #endif
315
316                 FD_SET( tcps, &readfds );
317
318 #ifndef HAVE_WINSOCK
319                 nfds = slap_daemon.sd_nfds;
320 #else
321                 nfds = dtblsize;
322 #endif
323
324                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
325
326                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
327 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
328                 tvp = NULL;
329 #else
330                 tvp = active_threads ? &zero : NULL;
331 #endif
332
333                 Debug( LDAP_DEBUG_CONNS,
334                         "daemon: select: tcps=%d active_threads=%d tvp=%s\n",
335                     tcps, active_threads,
336                         tvp == NULL ? "NULL" : "zero" );
337            
338
339                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
340
341                 switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
342                 case -1: {      /* failure - try again */
343                                 int err = errno;
344                                 if( err != EINTR ) {
345                                         Debug( LDAP_DEBUG_CONNS,
346                                                 "daemon: select failed (%d): %s\n",
347                                                 err,
348                                                 err >= 0 && err < sys_nerr
349                                                         ? sys_errlist[err] : "unknown",
350                                                 0 );
351
352                                         slapd_shutdown = -1;
353                                 }
354                         }
355                         continue;
356
357                 case 0:         /* timeout - let threads run */
358                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
359                             0, 0, 0 );
360                 ldap_pvt_thread_yield();
361                         continue;
362
363                 default:        /* something happened - deal with it */
364                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
365                                 ns, 0, 0 );
366                         /* FALL THRU */
367                 }
368
369                 if ( FD_ISSET( tcps, &readfds ) ) {
370                         int s;
371                         int len = sizeof(from);
372                         long id;
373
374                         if ( (s = accept( tcps,
375                                 (struct sockaddr *) &from, &len )) == -1 )
376                         {
377                                 int err = errno;
378                                 Debug( LDAP_DEBUG_ANY,
379                                     "daemon: accept(%d) failed errno %d (%s)\n", err,
380                                     tcps, err >= 0 && err < sys_nerr ?
381                                     sys_errlist[err] : "unknown");
382                                 continue;
383                         }
384
385                         assert( !FD_ISSET( 0, &slap_daemon.sd_actives) );
386                         assert( !FD_ISSET( 0, &slap_daemon.sd_readers) );
387                         assert( !FD_ISSET( 0, &slap_daemon.sd_writers) );
388
389 #ifndef HAVE_WINSOCK
390                         /* make sure descriptor number isn't too great */
391                         if ( s >= dtblsize ) {
392                                 Debug( LDAP_DEBUG_ANY,
393                                         "daemon: %d beyond descriptor table size %d\n",
394                                         s, dtblsize, 0 );
395                                 tcp_close(s);
396                                 continue;
397                         }
398 #endif
399                    
400                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %d\n",
401                                 s, 0, 0 );
402
403                         len = sizeof(from);
404                         if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
405                                 client_addr = inet_ntoa( from.sin_addr );
406
407 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
408                                 hp = gethostbyaddr( (char *)
409                                     &(from.sin_addr.s_addr),
410                                     sizeof(from.sin_addr.s_addr), AF_INET );
411
412                                 if(hp) {
413                                         char *p;
414                                         client_name = hp->h_name;
415
416                                         /* normalize the domain */
417                                         for ( p = client_name; *p; p++ ) {
418                                                 *p = TOLOWER( (unsigned char) *p );
419                                         }
420
421                                 } else {
422                                         client_name = NULL;
423                                 }
424 #else
425                                 client_name = NULL;
426 #endif
427
428                         } else {
429                                 client_name = NULL;;
430                                 client_addr = NULL;
431                         }
432
433 #ifdef HAVE_TCPD
434                         if(!hosts_ctl("slapd",
435                                 client_name != NULL ? client_name : STRING_UNKNOWN,
436                                 client_addr != NULL ? client_addr : STRING_UNKNOWN,
437                                 STRING_UNKNOWN))
438                         {
439                                 /* DENY ACCESS */
440                                 Statslog( LDAP_DEBUG_ANY,
441                                  "fd=%d connection from %s (%s) denied.\n",
442                                         s,
443                                         client_name == NULL ? "unknown" : client_name,
444                                         client_addr == NULL ? "unknown" : client_addr,
445                                   0, 0 );
446
447                                 tcp_close(s);
448                                 continue;
449                         }
450 #endif /* HAVE_TCPD */
451
452                         if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
453                                 Debug( LDAP_DEBUG_ANY,
454                                         "daemon: connection_init(%d, %s, %s) failed.\n",
455                                         s,
456                                         client_name == NULL ? "unknown" : client_name,
457                                         client_addr == NULL ? "unknown" : client_addr);
458                                 tcp_close(s);
459                                 continue;
460                         }
461
462                         Statslog( LDAP_DEBUG_STATS,
463                                 "daemon: conn=%d fd=%d connection from %s (%s) accepted.\n",
464                                 id, s,
465                                 client_name == NULL ? "unknown" : client_name,
466                                 client_addr == NULL ? "unknown" : client_addr,
467                                 0 );
468
469                         slapd_add( s );
470                         continue;
471                 }
472
473 #ifdef LDAP_DEBUG
474                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
475 #ifdef HAVE_WINSOCK
476                 for ( i = 0; i < readfds.fd_count; i++ )
477                 {
478                         Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r" );
479                 }
480                 for ( i = 0; i < writefds.fd_count; i++ )
481                 {
482                         Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w" );
483                 }
484 #else
485                 for ( i = 0; i < nfds; i++ ) {
486                         int     a, r, w;
487
488                         r = FD_ISSET( i, &readfds );
489                         w = FD_ISSET( i, &writefds );
490                         if ( i != tcps && (r || w) ) {
491                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
492                                     r ? "r" : "", w ? "w" : "" );
493                         }
494                 }
495 #endif
496                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
497 #endif
498
499                 /* loop through the writers */
500 #ifdef HAVE_WINSOCK
501                 for ( i = 0; i < writefds.fd_count; i++ ) {
502                         int wd = writefds.fd_array[i];
503
504                         if ( wd == tcps ) {
505                                 continue;
506                         }
507
508                         Debug( LDAP_DEBUG_CONNS,
509                                 "daemon: signalling write waiter on %d\n",
510                                 wd, 0, 0 );
511
512                         assert( FD_ISSET( wd, &slap_daemon.sd_actives) );
513
514                         slapd_clr_write( wd, 0 );
515                         if ( connection_write( wd ) < 0 ) {
516                                 FD_CLR( wd, &readfds );
517                                 slapd_close( wd );
518                         }
519                 }
520 #else
521                 for ( i = 0; i < nfds; i++ ) {
522                         if ( i == tcps ) {
523                                 continue;
524                         }
525                         if ( FD_ISSET( i, &writefds ) ) {
526                                 Debug( LDAP_DEBUG_CONNS,
527                                     "daemon: signaling write waiter on %d\n", i, 0, 0 );
528
529                                 assert( FD_ISSET( i, &slap_daemon.sd_actives) );
530
531                                 /* clear the write flag */
532                                 slapd_clr_write( i, 0 );
533                                 
534                                 if( connection_write( i ) < 0 ) { 
535                                         FD_CLR( i, &readfds );
536                                         slapd_close( i );
537                                 }
538                         }
539                 }
540 #endif
541
542 #ifdef HAVE_WINSOCK
543                 for ( i = 0; i < readfds.fd_count; i++ ) {
544                         int rd = readfds.fd_array[i];
545                         if ( rd == tcps ) {
546                                 continue;
547                         }
548                         Debug ( LDAP_DEBUG_CONNS,
549                                 "daemon: read activity on %d\n", rd, 0, 0 );
550                         assert( FD_ISSET( rd, &slap_daemon.sd_actives) );
551
552                         if ( connection_read( rd ) < 0 ) {
553                                 slapd_close( rd );
554                         }
555                 }
556 #else
557                 for ( i = 0; i < nfds; i++ ) {
558                         if ( i == tcps ) {
559                                 continue;
560                         }
561
562                         if ( FD_ISSET( i, &readfds ) ) {
563                                 Debug( LDAP_DEBUG_CONNS,
564                                     "daemon: read activity on %d\n", i, 0, 0 );
565
566                                 assert( FD_ISSET( i, &slap_daemon.sd_actives) );
567
568                                 if( connection_read( i ) < 0) {
569                                         slapd_close( i );
570                                 }
571                         }
572                 }
573 #endif
574                 ldap_pvt_thread_yield();
575         }
576
577         if( slapd_shutdown > 0 ) {
578                 Debug( LDAP_DEBUG_TRACE,
579                         "daemon: shutdown requested (%d) and initiated.\n",
580                         (int) slapd_shutdown, 0, 0 );
581
582         } else if ( slapd_shutdown < 0 ) {
583                 Debug( LDAP_DEBUG_TRACE,
584                         "daemon: abnormal condition (%d), shutdown initiated.\n",
585                         (int) slapd_shutdown, 0, 0 );
586         } else {
587                 Debug( LDAP_DEBUG_TRACE,
588                         "daemon: no active streams, shutdown initiated.\n",
589                         0, 0, 0 );
590         }
591
592         if( tcps >= 0 ) {
593                 tcp_close( tcps );
594         }
595
596         /* we only implement "quick" shutdown */
597         connections_shutdown();
598
599         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
600         Debug( LDAP_DEBUG_ANY,
601             "slapd shutdown: waiting for %d threads to terminate\n",
602             active_threads, 0, 0 );
603         while ( active_threads > 0 ) {
604                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
605         }
606         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
607
608         slapd_listener = 0;
609         return NULL;
610 }
611
612 int slapd_daemon( int inetd, int tcps )
613 {
614         int rc;
615         int *args = ch_malloc( sizeof( int[2] ) );
616         args[0] = inetd;
617         args[1] = tcps;
618
619     if ( !daemon_initialized ) sockinit();
620
621         connections_init();
622
623 #define SLAPD_LISTENER_THREAD 1
624 #if SLAPD_LISTENER_THREAD
625         /* listener as a separate THREAD */
626         rc = ldap_pvt_thread_create( &listener_tid,
627                 0, slapd_daemon_task, args );
628
629         if ( rc != 0 ) {
630                 Debug( LDAP_DEBUG_ANY,
631                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
632                 goto destory;
633         }
634
635         /* wait for the listener thread to complete */
636         ldap_pvt_thread_join( listener_tid, (void *) NULL );
637 #else
638         /* expermimental code */
639         listener_tid = pthread_self();
640         slapd_daemon_task( args );
641 #endif
642
643         rc = 0;
644
645 destory:
646         connections_destroy();
647
648 #ifdef HAVE_WINSOCK
649     WSACleanup( );
650 #endif
651
652         return rc;
653 }
654
655 #ifdef HAVE_WINSOCK2
656 void sockinit()
657 {
658     WORD wVersionRequested;
659         WSADATA wsaData;
660         int err;
661  
662         wVersionRequested = MAKEWORD( 2, 0 );
663  
664         err = WSAStartup( wVersionRequested, &wsaData );
665         if ( err != 0 ) {
666                 /* Tell the user that we couldn't find a usable */
667                 /* WinSock DLL.                                  */
668                 return;
669         }
670  
671         /* Confirm that the WinSock DLL supports 2.0.*/
672         /* Note that if the DLL supports versions greater    */
673         /* than 2.0 in addition to 2.0, it will still return */
674         /* 2.0 in wVersion since that is the version we      */
675         /* requested.                                        */
676  
677         if ( LOBYTE( wsaData.wVersion ) != 2 ||
678                 HIBYTE( wsaData.wVersion ) != 0 )
679         {
680             /* Tell the user that we couldn't find a usable */
681             /* WinSock DLL.                                  */
682             WSACleanup( );
683             return; 
684         }
685     daemon_initialized = 1;
686 }       /* The WinSock DLL is acceptable. Proceed. */
687
688 void hit_socket( void )
689 {
690         int s, on = 1;
691         extern struct sockaddr_in       bind_addr;
692
693         /* throw something at the socket to terminate the select() in the daemon thread. */
694         if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
695                 Debug( LDAP_DEBUG_TRACE, "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n", WSAGetLastError(), WSAGetLastErrorString(), 0 );
696         if ( ioctlsocket( s, FIONBIO, &on ) == -1 ) 
697                 Debug( LDAP_DEBUG_TRACE, "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n", s, WSAGetLastError(), WSAGetLastError() );
698
699         bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
700         if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) {
701                 /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */
702         }
703 }
704 #elif HAVE_WINSOCK
705 void sockinit()
706 {       WSADATA wsaData;
707         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
708             return( NULL );
709         }
710     daemon_initialized = 1;
711 }
712 else
713 void sockinit()
714 {
715     daemon_initialized = 1;
716     return;
717 }
718 #endif
719
720 void
721 slap_set_shutdown( int sig )
722 {
723         slapd_shutdown = sig;
724 #ifndef WIN32
725         if(slapd_listener) {
726                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
727         }
728 #else
729         hit_socket();
730 #endif
731         /* reinstall self */
732         (void) SIGNAL( sig, slap_set_shutdown );
733 }
734
735 void
736 slap_do_nothing( int sig )
737 {
738         /* reinstall self */
739         (void) SIGNAL( sig, slap_do_nothing );
740 }