Home | History | Annotate | Line # | Download | only in slapd
      1  1.3  christos /*	$NetBSD: main.c,v 1.4 2025/09/05 21:16:25 christos Exp $	*/
      2  1.2  christos 
      3  1.2  christos /* $OpenLDAP$ */
      4  1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  1.1     lukem  *
      6  1.4  christos  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  1.1     lukem  * All rights reserved.
      8  1.1     lukem  *
      9  1.1     lukem  * Redistribution and use in source and binary forms, with or without
     10  1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     11  1.1     lukem  * Public License.
     12  1.1     lukem  *
     13  1.1     lukem  * A copy of this license is available in the file LICENSE in the
     14  1.1     lukem  * top-level directory of the distribution or, alternatively, at
     15  1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     16  1.1     lukem  */
     17  1.1     lukem /* Portions Copyright (c) 1995 Regents of the University of Michigan.
     18  1.1     lukem  * All rights reserved.
     19  1.1     lukem  *
     20  1.1     lukem  * Redistribution and use in source and binary forms are permitted
     21  1.1     lukem  * provided that this notice is preserved and that due credit is given
     22  1.1     lukem  * to the University of Michigan at Ann Arbor. The name of the University
     23  1.1     lukem  * may not be used to endorse or promote products derived from this
     24  1.1     lukem  * software without specific prior written permission. This software
     25  1.1     lukem  * is provided ``as is'' without express or implied warranty.
     26  1.1     lukem  */
     27  1.1     lukem 
     28  1.2  christos #include <sys/cdefs.h>
     29  1.3  christos __RCSID("$NetBSD: main.c,v 1.4 2025/09/05 21:16:25 christos Exp $");
     30  1.2  christos 
     31  1.1     lukem #include "portable.h"
     32  1.1     lukem 
     33  1.1     lukem #include <stdio.h>
     34  1.1     lukem 
     35  1.1     lukem #include <ac/ctype.h>
     36  1.1     lukem #include <ac/socket.h>
     37  1.1     lukem #include <ac/string.h>
     38  1.1     lukem #include <ac/time.h>
     39  1.1     lukem #include <ac/unistd.h>
     40  1.1     lukem #include <ac/wait.h>
     41  1.1     lukem #include <ac/errno.h>
     42  1.1     lukem 
     43  1.1     lukem #include "slap.h"
     44  1.1     lukem #include "lutil.h"
     45  1.1     lukem #include "ldif.h"
     46  1.1     lukem 
     47  1.1     lukem #ifdef LDAP_SLAPI
     48  1.1     lukem #include "slapi/slapi.h"
     49  1.1     lukem #endif
     50  1.1     lukem 
     51  1.1     lukem #ifdef LDAP_SIGCHLD
     52  1.1     lukem static RETSIGTYPE wait4child( int sig );
     53  1.1     lukem #endif
     54  1.1     lukem 
     55  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
     56  1.1     lukem #define MAIN_RETURN(x) return
     57  1.1     lukem static struct sockaddr_in	bind_addr;
     58  1.1     lukem 
     59  1.1     lukem #define SERVICE_EXIT( e, n )	do { \
     60  1.1     lukem 	if ( is_NT_Service ) { \
     61  1.1     lukem 		lutil_ServiceStatus.dwWin32ExitCode				= (e); \
     62  1.1     lukem 		lutil_ServiceStatus.dwServiceSpecificExitCode	= (n); \
     63  1.1     lukem 	} \
     64  1.1     lukem } while ( 0 )
     65  1.1     lukem 
     66  1.1     lukem #else
     67  1.1     lukem #define SERVICE_EXIT( e, n )
     68  1.1     lukem #define MAIN_RETURN(x) return(x)
     69  1.1     lukem #endif
     70  1.1     lukem 
     71  1.1     lukem typedef int (MainFunc) LDAP_P(( int argc, char *argv[] ));
     72  1.1     lukem extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd,
     73  1.3  christos 	slaptest, slapauth, slapacl, slapschema, slapmodify;
     74  1.1     lukem 
     75  1.1     lukem static struct {
     76  1.1     lukem 	char *name;
     77  1.1     lukem 	MainFunc *func;
     78  1.1     lukem } tools[] = {
     79  1.1     lukem 	{"slapadd", slapadd},
     80  1.1     lukem 	{"slapcat", slapcat},
     81  1.1     lukem 	{"slapdn", slapdn},
     82  1.1     lukem 	{"slapindex", slapindex},
     83  1.3  christos 	{"slapmodify", slapmodify},
     84  1.1     lukem 	{"slappasswd", slappasswd},
     85  1.2  christos 	{"slapschema", slapschema},
     86  1.1     lukem 	{"slaptest", slaptest},
     87  1.1     lukem 	{"slapauth", slapauth},
     88  1.1     lukem 	{"slapacl", slapacl},
     89  1.1     lukem 	/* NOTE: new tools must be added in chronological order,
     90  1.1     lukem 	 * not in alphabetical order, because for backwards
     91  1.1     lukem 	 * compatibility name[4] is used to identify the
     92  1.1     lukem 	 * tools; so name[4]=='a' must refer to "slapadd" and
     93  1.1     lukem 	 * not to "slapauth".  Alphabetical order can be used
     94  1.1     lukem 	 * for tools whose name[4] is not used yet */
     95  1.1     lukem 	{NULL, NULL}
     96  1.1     lukem };
     97  1.1     lukem 
     98  1.1     lukem /*
     99  1.1     lukem  * when more than one slapd is running on one machine, each one might have
    100  1.1     lukem  * it's own LOCAL for syslogging and must have its own pid/args files
    101  1.1     lukem  */
    102  1.1     lukem 
    103  1.1     lukem #ifndef HAVE_MKVERSION
    104  1.1     lukem const char Versionstr[] =
    105  1.1     lukem 	OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
    106  1.1     lukem #endif
    107  1.1     lukem 
    108  1.2  christos extern OverlayInit slap_oinfo[];
    109  1.2  christos extern BackendInfo slap_binfo[];
    110  1.2  christos 
    111  1.1     lukem #define	CHECK_NONE	0x00
    112  1.1     lukem #define	CHECK_CONFIG	0x01
    113  1.1     lukem #define	CHECK_LOGLEVEL	0x02
    114  1.1     lukem static int check = CHECK_NONE;
    115  1.1     lukem static int version = 0;
    116  1.1     lukem 
    117  1.1     lukem void *slap_tls_ctx;
    118  1.1     lukem LDAP *slap_tls_ld;
    119  1.1     lukem 
    120  1.1     lukem static int
    121  1.1     lukem slapd_opt_slp( const char *val, void *arg )
    122  1.1     lukem {
    123  1.1     lukem #ifdef HAVE_SLP
    124  1.1     lukem 	/* NULL is default */
    125  1.1     lukem 	if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) {
    126  1.1     lukem 		slapd_register_slp = 1;
    127  1.1     lukem 		slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL;
    128  1.1     lukem 
    129  1.1     lukem 	} else if ( strcasecmp( val, "off" ) == 0 ) {
    130  1.1     lukem 		slapd_register_slp = 0;
    131  1.1     lukem 
    132  1.1     lukem 	/* NOTE: add support for URL specification? */
    133  1.1     lukem 
    134  1.1     lukem 	} else {
    135  1.1     lukem 		fprintf(stderr, "unrecognized value \"%s\" for SLP option\n", val );
    136  1.1     lukem 		return -1;
    137  1.1     lukem 	}
    138  1.1     lukem 
    139  1.1     lukem 	return 0;
    140  1.1     lukem 
    141  1.1     lukem #else
    142  1.1     lukem 	fputs( "slapd: SLP support is not available\n", stderr );
    143  1.1     lukem 	return 0;
    144  1.1     lukem #endif
    145  1.1     lukem }
    146  1.1     lukem 
    147  1.1     lukem /*
    148  1.1     lukem  * Option helper structure:
    149  1.1     lukem  *
    150  1.1     lukem  * oh_nam	is left-hand part of <option>[=<value>]
    151  1.1     lukem  * oh_fnc	is handler function
    152  1.1     lukem  * oh_arg	is an optional arg to oh_fnc
    153  1.1     lukem  * oh_usage	is the one-line usage string related to the option,
    154  1.1     lukem  *		which is assumed to start with <option>[=<value>]
    155  1.1     lukem  *
    156  1.1     lukem  * please leave valid options in the structure, and optionally #ifdef
    157  1.1     lukem  * their processing inside the helper, so that reasonable and helpful
    158  1.1     lukem  * error messages can be generated if a disabled option is requested.
    159  1.1     lukem  */
    160  1.1     lukem struct option_helper {
    161  1.1     lukem 	struct berval	oh_name;
    162  1.1     lukem 	int		(*oh_fnc)(const char *val, void *arg);
    163  1.1     lukem 	void		*oh_arg;
    164  1.1     lukem 	const char	*oh_usage;
    165  1.1     lukem } option_helpers[] = {
    166  1.1     lukem 	{ BER_BVC("slp"),	slapd_opt_slp,	NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" },
    167  1.1     lukem 	{ BER_BVNULL, 0, NULL, NULL }
    168  1.1     lukem };
    169  1.1     lukem 
    170  1.1     lukem static void
    171  1.1     lukem usage( char *name )
    172  1.1     lukem {
    173  1.1     lukem 	fprintf( stderr,
    174  1.1     lukem 		"usage: %s options\n", name );
    175  1.1     lukem 	fprintf( stderr,
    176  1.1     lukem 		"\t-4\t\tIPv4 only\n"
    177  1.3  christos #ifdef LDAP_PF_INET6
    178  1.1     lukem 		"\t-6\t\tIPv6 only\n"
    179  1.3  christos #endif
    180  1.3  christos 		"\t-T {acl|add|auth|cat|dn|index|modify|passwd|test}\n"
    181  1.1     lukem 		"\t\t\tRun in Tool mode\n"
    182  1.1     lukem 		"\t-c cookie\tSync cookie of consumer\n"
    183  1.1     lukem 		"\t-d level\tDebug level" "\n"
    184  1.1     lukem 		"\t-f filename\tConfiguration file\n"
    185  1.1     lukem 		"\t-F dir\tConfiguration directory\n"
    186  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    187  1.1     lukem 		"\t-g group\tGroup (id or name) to run as\n"
    188  1.1     lukem #endif
    189  1.1     lukem 		"\t-h URLs\t\tList of URLs to serve\n"
    190  1.1     lukem #ifdef SLAP_DEFAULT_SYSLOG_USER
    191  1.1     lukem 		"\t-l facility\tSyslog facility (default: LOCAL4)\n"
    192  1.1     lukem #endif
    193  1.1     lukem 		"\t-n serverName\tService name\n"
    194  1.1     lukem 		"\t-o <opt>[=val] generic means to specify options" );
    195  1.1     lukem 	if ( !BER_BVISNULL( &option_helpers[0].oh_name ) ) {
    196  1.1     lukem 		int	i;
    197  1.1     lukem 
    198  1.1     lukem 		fprintf( stderr, "; supported options:\n" );
    199  1.1     lukem 		for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++) {
    200  1.1     lukem 			fprintf( stderr, "\t\t%s\n", option_helpers[i].oh_usage );
    201  1.1     lukem 		}
    202  1.1     lukem 	} else {
    203  1.1     lukem 		fprintf( stderr, "\n" );
    204  1.1     lukem 	}
    205  1.1     lukem 	fprintf( stderr,
    206  1.1     lukem #ifdef HAVE_CHROOT
    207  1.1     lukem 		"\t-r directory\tSandbox directory to chroot to\n"
    208  1.1     lukem #endif
    209  1.1     lukem 		"\t-s level\tSyslog level\n"
    210  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    211  1.1     lukem 		"\t-u user\t\tUser (id or name) to run as\n"
    212  1.1     lukem #endif
    213  1.2  christos 		"\t-V\t\tprint version info (-VV exit afterwards, -VVV print\n"
    214  1.2  christos 		"\t\t\tinfo about static overlays and backends)\n"
    215  1.1     lukem     );
    216  1.1     lukem }
    217  1.1     lukem 
    218  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    219  1.1     lukem void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
    220  1.1     lukem #else
    221  1.1     lukem int main( int argc, char **argv )
    222  1.1     lukem #endif
    223  1.1     lukem {
    224  1.1     lukem 	int		i, no_detach = 0;
    225  1.1     lukem 	int		rc = 1;
    226  1.1     lukem 	char *urls = NULL;
    227  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    228  1.1     lukem 	char *username = NULL;
    229  1.1     lukem 	char *groupname = NULL;
    230  1.1     lukem #endif
    231  1.1     lukem #if defined(HAVE_CHROOT)
    232  1.1     lukem 	char *sandbox = NULL;
    233  1.1     lukem #endif
    234  1.1     lukem #ifdef SLAP_DEFAULT_SYSLOG_USER
    235  1.1     lukem 	int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
    236  1.1     lukem #endif
    237  1.1     lukem 
    238  1.2  christos #ifndef HAVE_WINSOCK
    239  1.2  christos 	int pid, waitfds[2];
    240  1.2  christos #endif
    241  1.1     lukem 	int g_argc = argc;
    242  1.1     lukem 	char **g_argv = argv;
    243  1.1     lukem 
    244  1.1     lukem 	char *configfile = NULL;
    245  1.1     lukem 	char *configdir = NULL;
    246  1.1     lukem 	int serverMode = SLAP_SERVER_MODE;
    247  1.1     lukem 
    248  1.1     lukem 	struct sync_cookie *scp = NULL;
    249  1.1     lukem 	struct sync_cookie *scp_entry = NULL;
    250  1.1     lukem 
    251  1.1     lukem 	char *serverNamePrefix = "";
    252  1.1     lukem 	size_t	l;
    253  1.1     lukem 
    254  1.1     lukem 	int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0;
    255  1.1     lukem 	int firstopt = 1;
    256  1.1     lukem 
    257  1.1     lukem #ifdef CSRIMALLOC
    258  1.1     lukem 	FILE *leakfile;
    259  1.1     lukem 	if( ( leakfile = fopen( "slapd.leak", "w" )) == NULL ) {
    260  1.1     lukem 		leakfile = stderr;
    261  1.1     lukem 	}
    262  1.1     lukem #endif
    263  1.1     lukem 
    264  1.1     lukem 	slap_sl_mem_init();
    265  1.1     lukem 
    266  1.4  christos 	(void) ldap_pvt_thread_initialize();
    267  1.4  christos 	ldap_pvt_thread_mutex_init( &logfile_mutex );
    268  1.4  christos 
    269  1.4  christos #ifdef HAVE_TLS
    270  1.4  christos 	rc = ldap_create( &slap_tls_ld );
    271  1.4  christos 	if ( rc ) {
    272  1.4  christos 		MAIN_RETURN( rc );
    273  1.4  christos 	}
    274  1.4  christos 	/* Library defaults to full certificate checking. This is correct when
    275  1.4  christos 	 * a client is verifying a server because all servers should have a
    276  1.4  christos 	 * valid cert. But few clients have valid certs, so we want our default
    277  1.4  christos 	 * to be no checking. The config file can override this as usual.
    278  1.4  christos 	 */
    279  1.4  christos 	rc = LDAP_OPT_X_TLS_NEVER;
    280  1.4  christos 	(void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc );
    281  1.4  christos #endif
    282  1.2  christos 
    283  1.4  christos 	global_host = ldap_pvt_get_fqdn( NULL );
    284  1.4  christos 	ber_str2bv( global_host, 0, 0, &global_host_bv );
    285  1.1     lukem 
    286  1.1     lukem 	serverName = lutil_progname( "slapd", argc, argv );
    287  1.1     lukem 
    288  1.1     lukem 	if ( strcmp( serverName, "slapd" ) ) {
    289  1.2  christos #ifdef DEBUG_CLOSE
    290  1.2  christos 		extern void slapd_debug_close();
    291  1.2  christos 		slapd_debug_close();
    292  1.2  christos #endif
    293  1.1     lukem 		for (i=0; tools[i].name; i++) {
    294  1.1     lukem 			if ( !strcmp( serverName, tools[i].name ) ) {
    295  1.1     lukem 				rc = tools[i].func(argc, argv);
    296  1.1     lukem 				MAIN_RETURN(rc);
    297  1.1     lukem 			}
    298  1.1     lukem 		}
    299  1.1     lukem 	}
    300  1.1     lukem 
    301  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    302  1.1     lukem 	{
    303  1.1     lukem 		int *ip;
    304  1.1     lukem 		char *newConfigFile;
    305  1.1     lukem 		char *newConfigDir;
    306  1.1     lukem 		char *newUrls;
    307  1.1     lukem 		char *regService = NULL;
    308  1.1     lukem 
    309  1.1     lukem 		if ( is_NT_Service ) {
    310  1.1     lukem 			lutil_CommenceStartupProcessing( serverName, slap_sig_shutdown );
    311  1.1     lukem 			if ( strcmp(serverName, SERVICE_NAME) )
    312  1.1     lukem 			    regService = serverName;
    313  1.1     lukem 		}
    314  1.1     lukem 
    315  1.1     lukem 		ip = (int*)lutil_getRegParam( regService, "DebugLevel" );
    316  1.1     lukem 		if ( ip != NULL ) {
    317  1.1     lukem 			slap_debug = *ip;
    318  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
    319  1.3  christos 				"new debug level from registry is: %d\n", slap_debug );
    320  1.1     lukem 		}
    321  1.1     lukem 
    322  1.1     lukem 		newUrls = (char *) lutil_getRegParam(regService, "Urls");
    323  1.1     lukem 		if (newUrls) {
    324  1.1     lukem 		    urls = ch_strdup(newUrls);
    325  1.1     lukem 		    Debug(LDAP_DEBUG_ANY, "new urls from registry: %s\n",
    326  1.3  christos 				urls );
    327  1.1     lukem 		}
    328  1.1     lukem 
    329  1.1     lukem 		newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
    330  1.1     lukem 		if ( newConfigFile != NULL ) {
    331  1.2  christos 			configfile = ch_strdup(newConfigFile);
    332  1.3  christos 			Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile );
    333  1.1     lukem 		}
    334  1.1     lukem 
    335  1.1     lukem 		newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" );
    336  1.1     lukem 		if ( newConfigDir != NULL ) {
    337  1.2  christos 			configdir = ch_strdup(newConfigDir);
    338  1.3  christos 			Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir );
    339  1.1     lukem 		}
    340  1.1     lukem 	}
    341  1.1     lukem #endif
    342  1.1     lukem 
    343  1.1     lukem 	while ( (i = getopt( argc, argv,
    344  1.1     lukem 			     "c:d:f:F:h:n:o:s:tT:V"
    345  1.1     lukem #ifdef LDAP_PF_INET6
    346  1.1     lukem 				"46"
    347  1.1     lukem #endif
    348  1.1     lukem #ifdef HAVE_CHROOT
    349  1.1     lukem 				"r:"
    350  1.1     lukem #endif
    351  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    352  1.1     lukem 				"S:"
    353  1.1     lukem #ifdef LOG_LOCAL4
    354  1.1     lukem 				"l:"
    355  1.1     lukem #endif
    356  1.1     lukem #endif
    357  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    358  1.1     lukem 				"u:g:"
    359  1.1     lukem #endif
    360  1.1     lukem 			     )) != EOF ) {
    361  1.1     lukem 		switch ( i ) {
    362  1.1     lukem 		case '4':
    363  1.1     lukem 			slap_inet4or6 = AF_INET;
    364  1.1     lukem 			break;
    365  1.3  christos #ifdef LDAP_PF_INET6
    366  1.1     lukem 		case '6':
    367  1.1     lukem 			slap_inet4or6 = AF_INET6;
    368  1.1     lukem 			break;
    369  1.1     lukem #endif
    370  1.1     lukem 
    371  1.1     lukem 		case 'h':	/* listen URLs */
    372  1.3  christos 			urls = optarg;
    373  1.1     lukem 			break;
    374  1.1     lukem 
    375  1.3  christos 		case 'c':	/* provide sync cookie, override if exist in consumer */
    376  1.1     lukem 			scp = (struct sync_cookie *) ch_calloc( 1,
    377  1.1     lukem 										sizeof( struct sync_cookie ));
    378  1.1     lukem 			ber_str2bv( optarg, 0, 1, &scp->octet_str );
    379  1.1     lukem 
    380  1.1     lukem 			/* This only parses out the rid at this point */
    381  1.1     lukem 			slap_parse_sync_cookie( scp, NULL );
    382  1.1     lukem 
    383  1.1     lukem 			if ( scp->rid == -1 ) {
    384  1.1     lukem 				Debug( LDAP_DEBUG_ANY,
    385  1.1     lukem 						"main: invalid cookie \"%s\"\n",
    386  1.3  christos 						optarg );
    387  1.1     lukem 				slap_sync_cookie_free( scp, 1 );
    388  1.1     lukem 				goto destroy;
    389  1.1     lukem 			}
    390  1.1     lukem 
    391  1.1     lukem 			LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) {
    392  1.1     lukem 				if ( scp->rid == scp_entry->rid ) {
    393  1.1     lukem 					Debug( LDAP_DEBUG_ANY,
    394  1.3  christos 						    "main: duplicated replica id in cookies\n" );
    395  1.1     lukem 					slap_sync_cookie_free( scp, 1 );
    396  1.1     lukem 					goto destroy;
    397  1.1     lukem 				}
    398  1.1     lukem 			}
    399  1.1     lukem 			LDAP_STAILQ_INSERT_TAIL( &slap_sync_cookie, scp, sc_next );
    400  1.1     lukem 			break;
    401  1.1     lukem 
    402  1.1     lukem 		case 'd': {	/* set debug level and 'do not detach' flag */
    403  1.1     lukem 			int	level = 0;
    404  1.1     lukem 
    405  1.1     lukem 			if ( strcmp( optarg, "?" ) == 0 ) {
    406  1.1     lukem 				check |= CHECK_LOGLEVEL;
    407  1.1     lukem 				break;
    408  1.1     lukem 			}
    409  1.1     lukem 
    410  1.1     lukem 			no_detach = 1;
    411  1.4  christos 			if ( slap_parse_debug_level( optarg, &level, 0 ) ) {
    412  1.1     lukem 				goto destroy;
    413  1.1     lukem 			}
    414  1.1     lukem #ifdef LDAP_DEBUG
    415  1.1     lukem 			slap_debug |= level;
    416  1.1     lukem #else
    417  1.1     lukem 			if ( level != 0 )
    418  1.1     lukem 				fputs( "must compile with LDAP_DEBUG for debugging\n",
    419  1.1     lukem 				       stderr );
    420  1.1     lukem #endif
    421  1.1     lukem 			} break;
    422  1.1     lukem 
    423  1.1     lukem 		case 'f':	/* read config file */
    424  1.3  christos 			configfile = optarg;
    425  1.1     lukem 			break;
    426  1.1     lukem 
    427  1.1     lukem 		case 'F':	/* use config dir */
    428  1.3  christos 			configdir = optarg;
    429  1.1     lukem 			break;
    430  1.1     lukem 
    431  1.1     lukem 		case 'o': {
    432  1.1     lukem 			char		*val = strchr( optarg, '=' );
    433  1.1     lukem 			struct berval	opt;
    434  1.1     lukem 
    435  1.1     lukem 			opt.bv_val = optarg;
    436  1.1     lukem 
    437  1.1     lukem 			if ( val ) {
    438  1.1     lukem 				opt.bv_len = ( val - optarg );
    439  1.1     lukem 				val++;
    440  1.1     lukem 
    441  1.1     lukem 			} else {
    442  1.1     lukem 				opt.bv_len = strlen( optarg );
    443  1.1     lukem 			}
    444  1.1     lukem 
    445  1.1     lukem 			for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++ ) {
    446  1.1     lukem 				if ( ber_bvstrcasecmp( &option_helpers[i].oh_name, &opt ) == 0 ) {
    447  1.1     lukem 					assert( option_helpers[i].oh_fnc != NULL );
    448  1.1     lukem 					if ( (*option_helpers[i].oh_fnc)( val, option_helpers[i].oh_arg ) == -1 ) {
    449  1.1     lukem 						/* we assume the option parsing helper
    450  1.1     lukem 						 * issues appropriate and self-explanatory
    451  1.1     lukem 						 * error messages... */
    452  1.1     lukem 						goto stop;
    453  1.1     lukem 					}
    454  1.1     lukem 					break;
    455  1.1     lukem 				}
    456  1.1     lukem 			}
    457  1.1     lukem 
    458  1.1     lukem 			if ( BER_BVISNULL( &option_helpers[i].oh_name ) ) {
    459  1.1     lukem 				goto unhandled_option;
    460  1.1     lukem 			}
    461  1.1     lukem 			break;
    462  1.1     lukem 		}
    463  1.1     lukem 
    464  1.1     lukem 		case 's':	/* set syslog level */
    465  1.1     lukem 			if ( strcmp( optarg, "?" ) == 0 ) {
    466  1.1     lukem 				check |= CHECK_LOGLEVEL;
    467  1.1     lukem 				break;
    468  1.1     lukem 			}
    469  1.1     lukem 
    470  1.4  christos 			if ( slap_parse_debug_level( optarg, &ldap_syslog, 1 ) ) {
    471  1.1     lukem 				goto destroy;
    472  1.1     lukem 			}
    473  1.1     lukem 			break;
    474  1.1     lukem 
    475  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    476  1.1     lukem 		case 'S':
    477  1.4  christos 			if ( slap_parse_syslog_level( optarg, &ldap_syslog_level ) ) {
    478  1.1     lukem 				goto destroy;
    479  1.1     lukem 			}
    480  1.1     lukem 			break;
    481  1.1     lukem 
    482  1.1     lukem #ifdef LOG_LOCAL4
    483  1.1     lukem 		case 'l':	/* set syslog local user */
    484  1.4  christos 			if ( slap_parse_syslog_user( optarg, &syslogUser ) ) {
    485  1.1     lukem 				goto destroy;
    486  1.1     lukem 			}
    487  1.1     lukem 			break;
    488  1.1     lukem #endif
    489  1.1     lukem #endif /* LDAP_DEBUG && LDAP_SYSLOG */
    490  1.1     lukem 
    491  1.1     lukem #ifdef HAVE_CHROOT
    492  1.1     lukem 		case 'r':
    493  1.3  christos 			sandbox = optarg;
    494  1.1     lukem 			break;
    495  1.1     lukem #endif
    496  1.1     lukem 
    497  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    498  1.1     lukem 		case 'u':	/* user name */
    499  1.3  christos 			username = optarg;
    500  1.1     lukem 			break;
    501  1.1     lukem 
    502  1.1     lukem 		case 'g':	/* group name */
    503  1.3  christos 			groupname = optarg;
    504  1.1     lukem 			break;
    505  1.1     lukem #endif /* SETUID && GETUID */
    506  1.1     lukem 
    507  1.1     lukem 		case 'n':  /* NT service name */
    508  1.3  christos 			serverName = optarg;
    509  1.1     lukem 			break;
    510  1.1     lukem 
    511  1.1     lukem 		case 't':
    512  1.1     lukem 			/* deprecated; use slaptest instead */
    513  1.1     lukem 			fprintf( stderr, "option -t deprecated; "
    514  1.1     lukem 				"use slaptest command instead\n" );
    515  1.1     lukem 			check |= CHECK_CONFIG;
    516  1.1     lukem 			break;
    517  1.1     lukem 
    518  1.1     lukem 		case 'V':
    519  1.1     lukem 			version++;
    520  1.1     lukem 			break;
    521  1.1     lukem 
    522  1.1     lukem 		case 'T':
    523  1.1     lukem 			if ( firstopt == 0 ) {
    524  1.1     lukem 				fprintf( stderr, "warning: \"-T %s\" "
    525  1.1     lukem 					"should be the first option.\n",
    526  1.1     lukem 					optarg );
    527  1.1     lukem 			}
    528  1.1     lukem 
    529  1.2  christos #ifdef DEBUG_CLOSE
    530  1.2  christos 			extern void slapd_debug_close();
    531  1.2  christos 			slapd_debug_close();
    532  1.2  christos #endif
    533  1.1     lukem 			/* try full option string first */
    534  1.1     lukem 			for ( i = 0; tools[i].name; i++ ) {
    535  1.1     lukem 				if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) {
    536  1.1     lukem 					rc = tools[i].func( argc, argv );
    537  1.1     lukem 					MAIN_RETURN( rc );
    538  1.1     lukem 				}
    539  1.1     lukem 			}
    540  1.1     lukem 
    541  1.1     lukem 			/* try bits of option string (backward compatibility for single char) */
    542  1.1     lukem 			l = strlen( optarg );
    543  1.1     lukem 			for ( i = 0; tools[i].name; i++ ) {
    544  1.1     lukem 				if ( strncmp( optarg, &tools[i].name[4], l ) == 0 ) {
    545  1.1     lukem 					rc = tools[i].func( argc, argv );
    546  1.1     lukem 					MAIN_RETURN( rc );
    547  1.1     lukem 				}
    548  1.1     lukem 			}
    549  1.1     lukem 
    550  1.1     lukem 			/* issue error */
    551  1.1     lukem 			serverName = optarg;
    552  1.1     lukem 			serverNamePrefix = "slap";
    553  1.1     lukem 			fprintf( stderr, "program name \"%s%s\" unrecognized; "
    554  1.1     lukem 					"aborting...\n", serverNamePrefix, serverName );
    555  1.1     lukem 			/* FALLTHRU */
    556  1.1     lukem 		default:
    557  1.1     lukem unhandled_option:;
    558  1.1     lukem 			usage( argv[0] );
    559  1.1     lukem 			rc = 1;
    560  1.1     lukem 			SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
    561  1.1     lukem 			goto stop;
    562  1.1     lukem 		}
    563  1.1     lukem 
    564  1.1     lukem 		if ( firstopt ) {
    565  1.1     lukem 			firstopt = 0;
    566  1.1     lukem 		}
    567  1.1     lukem 	}
    568  1.1     lukem 
    569  1.2  christos 	if ( optind != argc )
    570  1.2  christos 		goto unhandled_option;
    571  1.2  christos 
    572  1.4  christos 	ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, slap_debug_print);
    573  1.1     lukem 	ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
    574  1.1     lukem 	ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
    575  1.1     lukem 	ldif_debug = slap_debug;
    576  1.4  christos 	slap_debug_orig = slap_debug;
    577  1.1     lukem 
    578  1.1     lukem 	if ( version ) {
    579  1.1     lukem 		fprintf( stderr, "%s\n", Versionstr );
    580  1.2  christos 		if ( version > 2 ) {
    581  1.2  christos 			if ( slap_oinfo[0].ov_type ) {
    582  1.2  christos 				fprintf( stderr, "Included static overlays:\n");
    583  1.2  christos 				for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) {
    584  1.2  christos 					fprintf( stderr, "    %s\n", slap_oinfo[i].ov_type );
    585  1.2  christos 				}
    586  1.2  christos 			}
    587  1.2  christos 			if ( slap_binfo[0].bi_type ) {
    588  1.2  christos 				fprintf( stderr, "Included static backends:\n");
    589  1.2  christos 				for ( i= 0 ; slap_binfo[i].bi_type; i++ ) {
    590  1.2  christos 					fprintf( stderr, "    %s\n", slap_binfo[i].bi_type );
    591  1.2  christos 				}
    592  1.2  christos 			}
    593  1.2  christos 		}
    594  1.2  christos 
    595  1.1     lukem 		if ( version > 1 ) goto stop;
    596  1.1     lukem 	}
    597  1.1     lukem 
    598  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    599  1.1     lukem 	{
    600  1.1     lukem 		char *logName;
    601  1.1     lukem #ifdef HAVE_EBCDIC
    602  1.1     lukem 		logName = ch_strdup( serverName );
    603  1.1     lukem 		__atoe( logName );
    604  1.1     lukem #else
    605  1.1     lukem 		logName = serverName;
    606  1.1     lukem #endif
    607  1.1     lukem 
    608  1.1     lukem #ifdef LOG_LOCAL4
    609  1.1     lukem 		openlog( logName, OPENLOG_OPTIONS, syslogUser );
    610  1.1     lukem #elif defined LOG_DEBUG
    611  1.1     lukem 		openlog( logName, OPENLOG_OPTIONS );
    612  1.1     lukem #endif
    613  1.1     lukem #ifdef HAVE_EBCDIC
    614  1.1     lukem 		free( logName );
    615  1.1     lukem #endif
    616  1.1     lukem 	}
    617  1.1     lukem #endif /* LDAP_DEBUG && LDAP_SYSLOG */
    618  1.1     lukem 
    619  1.3  christos 	Debug( LDAP_DEBUG_ANY, "%s", Versionstr );
    620  1.1     lukem 
    621  1.1     lukem 	if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) {
    622  1.1     lukem 		rc = 1;
    623  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
    624  1.1     lukem 		goto stop;
    625  1.1     lukem 	}
    626  1.1     lukem 
    627  1.1     lukem #if defined(HAVE_CHROOT)
    628  1.1     lukem 	if ( sandbox ) {
    629  1.1     lukem 		if ( chdir( sandbox ) ) {
    630  1.1     lukem 			perror("chdir");
    631  1.1     lukem 			rc = 1;
    632  1.1     lukem 			goto stop;
    633  1.1     lukem 		}
    634  1.1     lukem 		if ( chroot( sandbox ) ) {
    635  1.1     lukem 			perror("chroot");
    636  1.1     lukem 			rc = 1;
    637  1.1     lukem 			goto stop;
    638  1.1     lukem 		}
    639  1.2  christos 		if ( chdir( "/" ) ) {
    640  1.2  christos 			perror("chdir");
    641  1.2  christos 			rc = 1;
    642  1.2  christos 			goto stop;
    643  1.2  christos 		}
    644  1.1     lukem 	}
    645  1.1     lukem #endif
    646  1.1     lukem 
    647  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    648  1.1     lukem 	if ( username != NULL || groupname != NULL ) {
    649  1.1     lukem 		slap_init_user( username, groupname );
    650  1.1     lukem 	}
    651  1.1     lukem #endif
    652  1.1     lukem 
    653  1.1     lukem 	extops_init();
    654  1.1     lukem 	lutil_passwd_init();
    655  1.1     lukem 
    656  1.1     lukem 	rc = slap_init( serverMode, serverName );
    657  1.1     lukem 	if ( rc ) {
    658  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
    659  1.1     lukem 		goto destroy;
    660  1.1     lukem 	}
    661  1.1     lukem 
    662  1.1     lukem 	if ( read_config( configfile, configdir ) != 0 ) {
    663  1.1     lukem 		rc = 1;
    664  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
    665  1.1     lukem 
    666  1.1     lukem 		if ( check & CHECK_CONFIG ) {
    667  1.1     lukem 			fprintf( stderr, "config check failed\n" );
    668  1.1     lukem 		}
    669  1.1     lukem 
    670  1.1     lukem 		goto destroy;
    671  1.1     lukem 	}
    672  1.1     lukem 
    673  1.4  christos 	rc = slap_parse_debug_unknowns();
    674  1.4  christos 	if ( rc )
    675  1.4  christos 		goto destroy;
    676  1.1     lukem 
    677  1.1     lukem 	if ( check & CHECK_LOGLEVEL ) {
    678  1.1     lukem 		rc = 0;
    679  1.1     lukem 		goto destroy;
    680  1.1     lukem 	}
    681  1.1     lukem 
    682  1.1     lukem 	if ( check & CHECK_CONFIG ) {
    683  1.1     lukem 		fprintf( stderr, "config check succeeded\n" );
    684  1.1     lukem 
    685  1.1     lukem 		check &= ~CHECK_CONFIG;
    686  1.1     lukem 		if ( check == CHECK_NONE ) {
    687  1.1     lukem 			rc = 0;
    688  1.1     lukem 			goto destroy;
    689  1.1     lukem 		}
    690  1.1     lukem 	}
    691  1.1     lukem 
    692  1.2  christos 	if ( glue_sub_attach( 0 ) != 0 ) {
    693  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    694  1.3  christos 		    "subordinate config error\n" );
    695  1.1     lukem 
    696  1.1     lukem 		goto destroy;
    697  1.1     lukem 	}
    698  1.1     lukem 
    699  1.1     lukem 	if ( slap_schema_check( ) != 0 ) {
    700  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    701  1.3  christos 		    "schema prep error\n" );
    702  1.1     lukem 
    703  1.1     lukem 		goto destroy;
    704  1.1     lukem 	}
    705  1.1     lukem 
    706  1.1     lukem #ifdef HAVE_TLS
    707  1.3  christos 	rc = ldap_pvt_tls_init( 1 );
    708  1.1     lukem 	if( rc != 0) {
    709  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    710  1.1     lukem 		    "main: TLS init failed: %d\n",
    711  1.3  christos 		    rc );
    712  1.1     lukem 		rc = 1;
    713  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
    714  1.1     lukem 		goto destroy;
    715  1.1     lukem 	}
    716  1.1     lukem 
    717  1.1     lukem 	{
    718  1.1     lukem 		int opt = 1;
    719  1.1     lukem 
    720  1.1     lukem 		/* Force new ctx to be created */
    721  1.1     lukem 		rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
    722  1.1     lukem 		if( rc == 0 ) {
    723  1.1     lukem 			/* The ctx's refcount is bumped up here */
    724  1.1     lukem 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
    725  1.1     lukem 			load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
    726  1.1     lukem 		} else if ( rc != LDAP_NOT_SUPPORTED ) {
    727  1.4  christos 			char *errmsg = NULL;
    728  1.4  christos 			ldap_get_option( slap_tls_ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &errmsg );
    729  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
    730  1.4  christos 			    "main: TLS init def ctx failed: %d %s\n",
    731  1.4  christos 			    rc, errmsg ? errmsg : "" );
    732  1.4  christos 			ldap_memfree( errmsg );
    733  1.1     lukem 			rc = 1;
    734  1.1     lukem 			SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
    735  1.1     lukem 			goto destroy;
    736  1.1     lukem 		}
    737  1.1     lukem 	}
    738  1.1     lukem #endif
    739  1.1     lukem 
    740  1.1     lukem #ifdef HAVE_CYRUS_SASL
    741  1.1     lukem 	if( sasl_host == NULL ) {
    742  1.1     lukem 		sasl_host = ch_strdup( global_host );
    743  1.1     lukem 	}
    744  1.1     lukem #endif
    745  1.1     lukem 
    746  1.1     lukem 	(void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake );
    747  1.1     lukem 	(void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown );
    748  1.1     lukem 
    749  1.1     lukem #ifdef SIGPIPE
    750  1.1     lukem 	(void) SIGNAL( SIGPIPE, SIG_IGN );
    751  1.1     lukem #endif
    752  1.1     lukem #ifdef SIGHUP
    753  1.1     lukem 	(void) SIGNAL( SIGHUP, slap_sig_shutdown );
    754  1.1     lukem #endif
    755  1.1     lukem 	(void) SIGNAL( SIGINT, slap_sig_shutdown );
    756  1.1     lukem 	(void) SIGNAL( SIGTERM, slap_sig_shutdown );
    757  1.1     lukem #ifdef SIGTRAP
    758  1.1     lukem 	(void) SIGNAL( SIGTRAP, slap_sig_shutdown );
    759  1.1     lukem #endif
    760  1.1     lukem #ifdef LDAP_SIGCHLD
    761  1.1     lukem 	(void) SIGNAL( LDAP_SIGCHLD, wait4child );
    762  1.1     lukem #endif
    763  1.1     lukem #ifdef SIGBREAK
    764  1.1     lukem 	/* SIGBREAK is generated when Ctrl-Break is pressed. */
    765  1.1     lukem 	(void) SIGNAL( SIGBREAK, slap_sig_shutdown );
    766  1.1     lukem #endif
    767  1.1     lukem 
    768  1.1     lukem #ifndef HAVE_WINSOCK
    769  1.2  christos 	if ( !no_detach ) {
    770  1.2  christos 		if ( lutil_pair( waitfds ) < 0 ) {
    771  1.2  christos 			Debug( LDAP_DEBUG_ANY,
    772  1.2  christos 				"main: lutil_pair failed: %d\n",
    773  1.3  christos 				0 );
    774  1.2  christos 			rc = 1;
    775  1.2  christos 			goto destroy;
    776  1.2  christos 		}
    777  1.2  christos 		pid = lutil_detach( no_detach, 0 );
    778  1.2  christos 		if ( pid ) {
    779  1.2  christos 			char buf[4];
    780  1.2  christos 			rc = EXIT_SUCCESS;
    781  1.2  christos 			close( waitfds[1] );
    782  1.2  christos 			if ( read( waitfds[0], buf, 1 ) != 1 )
    783  1.2  christos 				rc = EXIT_FAILURE;
    784  1.2  christos 			_exit( rc );
    785  1.2  christos 		} else {
    786  1.2  christos 			close( waitfds[0] );
    787  1.2  christos 		}
    788  1.2  christos 	}
    789  1.1     lukem #endif /* HAVE_WINSOCK */
    790  1.1     lukem 
    791  1.1     lukem #ifdef CSRIMALLOC
    792  1.1     lukem 	mal_leaktrace(1);
    793  1.1     lukem #endif
    794  1.1     lukem 
    795  1.1     lukem 	if ( slapd_pid_file != NULL ) {
    796  1.1     lukem 		FILE *fp = fopen( slapd_pid_file, "w" );
    797  1.1     lukem 
    798  1.1     lukem 		if ( fp == NULL ) {
    799  1.3  christos 			char ebuf[128];
    800  1.1     lukem 			int save_errno = errno;
    801  1.1     lukem 
    802  1.1     lukem 			Debug( LDAP_DEBUG_ANY, "unable to open pid file "
    803  1.1     lukem 				"\"%s\": %d (%s)\n",
    804  1.1     lukem 				slapd_pid_file,
    805  1.3  christos 				save_errno, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
    806  1.1     lukem 
    807  1.1     lukem 			free( slapd_pid_file );
    808  1.1     lukem 			slapd_pid_file = NULL;
    809  1.1     lukem 
    810  1.1     lukem 			rc = 1;
    811  1.1     lukem 			goto destroy;
    812  1.1     lukem 		}
    813  1.1     lukem 		fprintf( fp, "%d\n", (int) getpid() );
    814  1.1     lukem 		fclose( fp );
    815  1.1     lukem 		slapd_pid_file_unlink = 1;
    816  1.1     lukem 	}
    817  1.1     lukem 
    818  1.1     lukem 	if ( slapd_args_file != NULL ) {
    819  1.1     lukem 		FILE *fp = fopen( slapd_args_file, "w" );
    820  1.1     lukem 
    821  1.1     lukem 		if ( fp == NULL ) {
    822  1.3  christos 			char ebuf[128];
    823  1.1     lukem 			int save_errno = errno;
    824  1.1     lukem 
    825  1.1     lukem 			Debug( LDAP_DEBUG_ANY, "unable to open args file "
    826  1.1     lukem 				"\"%s\": %d (%s)\n",
    827  1.1     lukem 				slapd_args_file,
    828  1.3  christos 				save_errno, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
    829  1.1     lukem 
    830  1.1     lukem 			free( slapd_args_file );
    831  1.1     lukem 			slapd_args_file = NULL;
    832  1.1     lukem 
    833  1.1     lukem 			rc = 1;
    834  1.1     lukem 			goto destroy;
    835  1.1     lukem 		}
    836  1.1     lukem 
    837  1.1     lukem 		for ( i = 0; i < g_argc; i++ ) {
    838  1.1     lukem 			fprintf( fp, "%s ", g_argv[i] );
    839  1.1     lukem 		}
    840  1.1     lukem 		fprintf( fp, "\n" );
    841  1.1     lukem 		fclose( fp );
    842  1.1     lukem 		slapd_args_file_unlink = 1;
    843  1.1     lukem 	}
    844  1.1     lukem 
    845  1.1     lukem 	/*
    846  1.1     lukem 	 * FIXME: moved here from slapd_daemon_task()
    847  1.1     lukem 	 * because back-monitor db_open() needs it
    848  1.1     lukem 	 */
    849  1.1     lukem 	time( &starttime );
    850  1.1     lukem 
    851  1.2  christos 	connections_init();
    852  1.2  christos 
    853  1.1     lukem 	if ( slap_startup( NULL ) != 0 ) {
    854  1.1     lukem 		rc = 1;
    855  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
    856  1.1     lukem 		goto shutdown;
    857  1.1     lukem 	}
    858  1.1     lukem 
    859  1.3  christos 	Debug( LDAP_DEBUG_ANY, "slapd starting\n" );
    860  1.1     lukem 
    861  1.2  christos #ifndef HAVE_WINSOCK
    862  1.2  christos 	if ( !no_detach ) {
    863  1.2  christos 		write( waitfds[1], "1", 1 );
    864  1.2  christos 		close( waitfds[1] );
    865  1.2  christos 	}
    866  1.2  christos #endif
    867  1.2  christos 
    868  1.1     lukem #ifdef HAVE_NT_EVENT_LOG
    869  1.1     lukem 	if (is_NT_Service)
    870  1.1     lukem 	lutil_LogStartedEvent( serverName, slap_debug, configfile ?
    871  1.1     lukem 		configfile : SLAPD_DEFAULT_CONFIGFILE , urls );
    872  1.1     lukem #endif
    873  1.1     lukem 
    874  1.1     lukem 	rc = slapd_daemon();
    875  1.1     lukem 
    876  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    877  1.1     lukem 	/* Throw away the event that we used during the startup process. */
    878  1.1     lukem 	if ( is_NT_Service )
    879  1.1     lukem 		ldap_pvt_thread_cond_destroy( &started_event );
    880  1.1     lukem #endif
    881  1.1     lukem 
    882  1.1     lukem shutdown:
    883  1.1     lukem 	/* remember an error during shutdown */
    884  1.1     lukem 	rc |= slap_shutdown( NULL );
    885  1.1     lukem 
    886  1.1     lukem destroy:
    887  1.1     lukem 	if ( check & CHECK_LOGLEVEL ) {
    888  1.1     lukem 		(void)loglevel_print( stdout );
    889  1.1     lukem 	}
    890  1.1     lukem 	/* remember an error during destroy */
    891  1.1     lukem 	rc |= slap_destroy();
    892  1.1     lukem 
    893  1.1     lukem 	while ( !LDAP_STAILQ_EMPTY( &slap_sync_cookie )) {
    894  1.1     lukem 		scp = LDAP_STAILQ_FIRST( &slap_sync_cookie );
    895  1.1     lukem 		LDAP_STAILQ_REMOVE_HEAD( &slap_sync_cookie, sc_next );
    896  1.1     lukem 		ch_free( scp );
    897  1.1     lukem 	}
    898  1.1     lukem 
    899  1.1     lukem #ifdef SLAPD_MODULES
    900  1.1     lukem 	module_kill();
    901  1.1     lukem #endif
    902  1.1     lukem 
    903  1.1     lukem 	extops_kill();
    904  1.1     lukem 
    905  1.1     lukem 	supported_feature_destroy();
    906  1.1     lukem 	entry_info_destroy();
    907  1.1     lukem 
    908  1.1     lukem stop:
    909  1.1     lukem #ifdef HAVE_NT_EVENT_LOG
    910  1.1     lukem 	if (is_NT_Service)
    911  1.1     lukem 	lutil_LogStoppedEvent( serverName );
    912  1.1     lukem #endif
    913  1.1     lukem 
    914  1.3  christos 	Debug( LDAP_DEBUG_ANY, "slapd stopped.\n" );
    915  1.1     lukem 
    916  1.1     lukem 
    917  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    918  1.1     lukem 	lutil_ReportShutdownComplete();
    919  1.1     lukem #endif
    920  1.1     lukem 
    921  1.1     lukem #ifdef LOG_DEBUG
    922  1.1     lukem     closelog();
    923  1.1     lukem #endif
    924  1.1     lukem 	slapd_daemon_destroy();
    925  1.1     lukem 
    926  1.1     lukem 	controls_destroy();
    927  1.1     lukem 
    928  1.1     lukem 	filter_destroy();
    929  1.1     lukem 
    930  1.1     lukem 	schema_destroy();
    931  1.1     lukem 
    932  1.1     lukem 	lutil_passwd_destroy();
    933  1.1     lukem 
    934  1.1     lukem #ifdef HAVE_TLS
    935  1.1     lukem 	if ( slap_tls_ld ) {
    936  1.1     lukem 		ldap_pvt_tls_ctx_free( slap_tls_ctx );
    937  1.1     lukem 		ldap_unbind_ext( slap_tls_ld, NULL, NULL );
    938  1.1     lukem 	}
    939  1.1     lukem 	ldap_pvt_tls_destroy();
    940  1.1     lukem #endif
    941  1.1     lukem 
    942  1.1     lukem 	slap_sasl_regexp_destroy();
    943  1.1     lukem 
    944  1.1     lukem 	if ( slapd_pid_file_unlink ) {
    945  1.1     lukem 		unlink( slapd_pid_file );
    946  1.1     lukem 	}
    947  1.1     lukem 	if ( slapd_args_file_unlink ) {
    948  1.1     lukem 		unlink( slapd_args_file );
    949  1.1     lukem 	}
    950  1.1     lukem 
    951  1.1     lukem 	config_destroy();
    952  1.1     lukem 
    953  1.2  christos 	if ( global_host )
    954  1.2  christos 		ch_free( global_host );
    955  1.1     lukem 
    956  1.1     lukem 	/* kludge, get symbols referenced */
    957  1.3  christos 	ldap_tavl_free( NULL, NULL );
    958  1.1     lukem 
    959  1.1     lukem #ifdef CSRIMALLOC
    960  1.1     lukem 	mal_dumpleaktrace( leakfile );
    961  1.1     lukem #endif
    962  1.1     lukem 
    963  1.4  christos 	ldap_pvt_thread_mutex_destroy( &logfile_mutex );
    964  1.1     lukem 	MAIN_RETURN(rc);
    965  1.1     lukem }
    966  1.1     lukem 
    967  1.1     lukem 
    968  1.1     lukem #ifdef LDAP_SIGCHLD
    969  1.1     lukem 
    970  1.1     lukem /*
    971  1.1     lukem  *  Catch and discard terminated child processes, to avoid zombies.
    972  1.1     lukem  */
    973  1.1     lukem 
    974  1.1     lukem static RETSIGTYPE
    975  1.1     lukem wait4child( int sig )
    976  1.1     lukem {
    977  1.1     lukem     int save_errno = errno;
    978  1.1     lukem 
    979  1.1     lukem #ifdef WNOHANG
    980  1.2  christos     do
    981  1.2  christos         errno = 0;
    982  1.1     lukem #ifdef HAVE_WAITPID
    983  1.2  christos     while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR );
    984  1.1     lukem #else
    985  1.2  christos     while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR );
    986  1.1     lukem #endif
    987  1.1     lukem #else
    988  1.1     lukem     (void) wait( NULL );
    989  1.1     lukem #endif
    990  1.1     lukem     (void) SIGNAL_REINSTALL( sig, wait4child );
    991  1.1     lukem     errno = save_errno;
    992  1.1     lukem }
    993  1.1     lukem 
    994  1.1     lukem #endif /* LDAP_SIGCHLD */
    995