Home | History | Annotate | Line # | Download | only in slapd
main.c revision 1.2
      1  1.2  christos /*	$NetBSD: main.c,v 1.2 2020/08/11 13:15:39 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.2  christos  * Copyright 1998-2020 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.2  christos __RCSID("$NetBSD: main.c,v 1.2 2020/08/11 13:15:39 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.2  christos 	slaptest, slapauth, slapacl, slapschema;
     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.1     lukem 	{"slappasswd", slappasswd},
     84  1.2  christos 	{"slapschema", slapschema},
     85  1.1     lukem 	{"slaptest", slaptest},
     86  1.1     lukem 	{"slapauth", slapauth},
     87  1.1     lukem 	{"slapacl", slapacl},
     88  1.1     lukem 	/* NOTE: new tools must be added in chronological order,
     89  1.1     lukem 	 * not in alphabetical order, because for backwards
     90  1.1     lukem 	 * compatibility name[4] is used to identify the
     91  1.1     lukem 	 * tools; so name[4]=='a' must refer to "slapadd" and
     92  1.1     lukem 	 * not to "slapauth".  Alphabetical order can be used
     93  1.1     lukem 	 * for tools whose name[4] is not used yet */
     94  1.1     lukem 	{NULL, NULL}
     95  1.1     lukem };
     96  1.1     lukem 
     97  1.1     lukem /*
     98  1.1     lukem  * when more than one slapd is running on one machine, each one might have
     99  1.1     lukem  * it's own LOCAL for syslogging and must have its own pid/args files
    100  1.1     lukem  */
    101  1.1     lukem 
    102  1.1     lukem #ifndef HAVE_MKVERSION
    103  1.1     lukem const char Versionstr[] =
    104  1.1     lukem 	OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
    105  1.1     lukem #endif
    106  1.1     lukem 
    107  1.2  christos extern OverlayInit slap_oinfo[];
    108  1.2  christos extern BackendInfo slap_binfo[];
    109  1.2  christos 
    110  1.1     lukem #define	CHECK_NONE	0x00
    111  1.1     lukem #define	CHECK_CONFIG	0x01
    112  1.1     lukem #define	CHECK_LOGLEVEL	0x02
    113  1.1     lukem static int check = CHECK_NONE;
    114  1.1     lukem static int version = 0;
    115  1.1     lukem 
    116  1.1     lukem void *slap_tls_ctx;
    117  1.1     lukem LDAP *slap_tls_ld;
    118  1.1     lukem 
    119  1.1     lukem static int
    120  1.1     lukem slapd_opt_slp( const char *val, void *arg )
    121  1.1     lukem {
    122  1.1     lukem #ifdef HAVE_SLP
    123  1.1     lukem 	/* NULL is default */
    124  1.1     lukem 	if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) {
    125  1.1     lukem 		slapd_register_slp = 1;
    126  1.1     lukem 		slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL;
    127  1.1     lukem 
    128  1.1     lukem 	} else if ( strcasecmp( val, "off" ) == 0 ) {
    129  1.1     lukem 		slapd_register_slp = 0;
    130  1.1     lukem 
    131  1.1     lukem 	/* NOTE: add support for URL specification? */
    132  1.1     lukem 
    133  1.1     lukem 	} else {
    134  1.1     lukem 		fprintf(stderr, "unrecognized value \"%s\" for SLP option\n", val );
    135  1.1     lukem 		return -1;
    136  1.1     lukem 	}
    137  1.1     lukem 
    138  1.1     lukem 	return 0;
    139  1.1     lukem 
    140  1.1     lukem #else
    141  1.1     lukem 	fputs( "slapd: SLP support is not available\n", stderr );
    142  1.1     lukem 	return 0;
    143  1.1     lukem #endif
    144  1.1     lukem }
    145  1.1     lukem 
    146  1.1     lukem /*
    147  1.1     lukem  * Option helper structure:
    148  1.1     lukem  *
    149  1.1     lukem  * oh_nam	is left-hand part of <option>[=<value>]
    150  1.1     lukem  * oh_fnc	is handler function
    151  1.1     lukem  * oh_arg	is an optional arg to oh_fnc
    152  1.1     lukem  * oh_usage	is the one-line usage string related to the option,
    153  1.1     lukem  *		which is assumed to start with <option>[=<value>]
    154  1.1     lukem  *
    155  1.1     lukem  * please leave valid options in the structure, and optionally #ifdef
    156  1.1     lukem  * their processing inside the helper, so that reasonable and helpful
    157  1.1     lukem  * error messages can be generated if a disabled option is requested.
    158  1.1     lukem  */
    159  1.1     lukem struct option_helper {
    160  1.1     lukem 	struct berval	oh_name;
    161  1.1     lukem 	int		(*oh_fnc)(const char *val, void *arg);
    162  1.1     lukem 	void		*oh_arg;
    163  1.1     lukem 	const char	*oh_usage;
    164  1.1     lukem } option_helpers[] = {
    165  1.1     lukem 	{ BER_BVC("slp"),	slapd_opt_slp,	NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" },
    166  1.1     lukem 	{ BER_BVNULL, 0, NULL, NULL }
    167  1.1     lukem };
    168  1.1     lukem 
    169  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    170  1.1     lukem #ifdef LOG_LOCAL4
    171  1.1     lukem int
    172  1.1     lukem parse_syslog_user( const char *arg, int *syslogUser )
    173  1.1     lukem {
    174  1.1     lukem 	static slap_verbmasks syslogUsers[] = {
    175  1.1     lukem 		{ BER_BVC( "LOCAL0" ), LOG_LOCAL0 },
    176  1.1     lukem 		{ BER_BVC( "LOCAL1" ), LOG_LOCAL1 },
    177  1.1     lukem 		{ BER_BVC( "LOCAL2" ), LOG_LOCAL2 },
    178  1.1     lukem 		{ BER_BVC( "LOCAL3" ), LOG_LOCAL3 },
    179  1.1     lukem 		{ BER_BVC( "LOCAL4" ), LOG_LOCAL4 },
    180  1.1     lukem 		{ BER_BVC( "LOCAL5" ), LOG_LOCAL5 },
    181  1.1     lukem 		{ BER_BVC( "LOCAL6" ), LOG_LOCAL6 },
    182  1.1     lukem 		{ BER_BVC( "LOCAL7" ), LOG_LOCAL7 },
    183  1.1     lukem #ifdef LOG_USER
    184  1.1     lukem 		{ BER_BVC( "USER" ), LOG_USER },
    185  1.1     lukem #endif /* LOG_USER */
    186  1.1     lukem #ifdef LOG_DAEMON
    187  1.1     lukem 		{ BER_BVC( "DAEMON" ), LOG_DAEMON },
    188  1.1     lukem #endif /* LOG_DAEMON */
    189  1.1     lukem 		{ BER_BVNULL, 0 }
    190  1.1     lukem 	};
    191  1.1     lukem 	int i = verb_to_mask( arg, syslogUsers );
    192  1.1     lukem 
    193  1.1     lukem 	if ( BER_BVISNULL( &syslogUsers[ i ].word ) ) {
    194  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    195  1.1     lukem 			"unrecognized syslog user \"%s\".\n",
    196  1.1     lukem 			arg, 0, 0 );
    197  1.1     lukem 		return 1;
    198  1.1     lukem 	}
    199  1.1     lukem 
    200  1.1     lukem 	*syslogUser = syslogUsers[ i ].mask;
    201  1.1     lukem 
    202  1.1     lukem 	return 0;
    203  1.1     lukem }
    204  1.1     lukem #endif /* LOG_LOCAL4 */
    205  1.1     lukem 
    206  1.1     lukem int
    207  1.1     lukem parse_syslog_level( const char *arg, int *levelp )
    208  1.1     lukem {
    209  1.1     lukem 	static slap_verbmasks	str2syslog_level[] = {
    210  1.1     lukem 		{ BER_BVC( "EMERG" ),	LOG_EMERG },
    211  1.1     lukem 		{ BER_BVC( "ALERT" ),	LOG_ALERT },
    212  1.1     lukem 		{ BER_BVC( "CRIT" ),	LOG_CRIT },
    213  1.1     lukem 		{ BER_BVC( "ERR" ),	LOG_ERR },
    214  1.1     lukem 		{ BER_BVC( "WARNING" ),	LOG_WARNING },
    215  1.1     lukem 		{ BER_BVC( "NOTICE" ),	LOG_NOTICE },
    216  1.1     lukem 		{ BER_BVC( "INFO" ),	LOG_INFO },
    217  1.1     lukem 		{ BER_BVC( "DEBUG" ),	LOG_DEBUG },
    218  1.1     lukem 		{ BER_BVNULL, 0 }
    219  1.1     lukem 	};
    220  1.1     lukem 	int i = verb_to_mask( arg, str2syslog_level );
    221  1.1     lukem 	if ( BER_BVISNULL( &str2syslog_level[ i ].word ) ) {
    222  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    223  1.1     lukem 			"unknown syslog level \"%s\".\n",
    224  1.1     lukem 			arg, 0, 0 );
    225  1.1     lukem 		return 1;
    226  1.1     lukem 	}
    227  1.1     lukem 
    228  1.1     lukem 	*levelp = str2syslog_level[ i ].mask;
    229  1.1     lukem 
    230  1.1     lukem 	return 0;
    231  1.1     lukem }
    232  1.1     lukem #endif /* LDAP_DEBUG && LDAP_SYSLOG */
    233  1.1     lukem 
    234  1.1     lukem int
    235  1.1     lukem parse_debug_unknowns( char **unknowns, int *levelp )
    236  1.1     lukem {
    237  1.1     lukem 	int i, level, rc = 0;
    238  1.1     lukem 
    239  1.1     lukem 	for ( i = 0; unknowns[ i ] != NULL; i++ ) {
    240  1.1     lukem 		level = 0;
    241  1.1     lukem 		if ( str2loglevel( unknowns[ i ], &level )) {
    242  1.1     lukem 			fprintf( stderr,
    243  1.1     lukem 				"unrecognized log level \"%s\"\n", unknowns[ i ] );
    244  1.1     lukem 			rc = 1;
    245  1.1     lukem 		} else {
    246  1.1     lukem 			*levelp |= level;
    247  1.1     lukem 		}
    248  1.1     lukem 	}
    249  1.1     lukem 	return rc;
    250  1.1     lukem }
    251  1.1     lukem 
    252  1.1     lukem int
    253  1.1     lukem parse_debug_level( const char *arg, int *levelp, char ***unknowns )
    254  1.1     lukem {
    255  1.1     lukem 	int	level;
    256  1.1     lukem 
    257  1.1     lukem 	if ( arg && arg[ 0 ] != '-' && !isdigit( (unsigned char) arg[ 0 ] ) )
    258  1.1     lukem 	{
    259  1.1     lukem 		int	i;
    260  1.1     lukem 		char	**levels;
    261  1.1     lukem 
    262  1.1     lukem 		levels = ldap_str2charray( arg, "," );
    263  1.1     lukem 
    264  1.1     lukem 		for ( i = 0; levels[ i ] != NULL; i++ ) {
    265  1.1     lukem 			level = 0;
    266  1.1     lukem 
    267  1.1     lukem 			if ( str2loglevel( levels[ i ], &level ) ) {
    268  1.1     lukem 				/* remember this for later */
    269  1.1     lukem 				ldap_charray_add( unknowns, levels[ i ] );
    270  1.1     lukem 				fprintf( stderr,
    271  1.1     lukem 					"unrecognized log level \"%s\" (deferred)\n",
    272  1.1     lukem 					levels[ i ] );
    273  1.1     lukem 			} else {
    274  1.1     lukem 				*levelp |= level;
    275  1.1     lukem 			}
    276  1.1     lukem 		}
    277  1.1     lukem 
    278  1.1     lukem 		ldap_charray_free( levels );
    279  1.1     lukem 
    280  1.1     lukem 	} else {
    281  1.2  christos 		int rc;
    282  1.2  christos 
    283  1.2  christos 		if ( arg[0] == '-' ) {
    284  1.2  christos 			rc = lutil_atoix( &level, arg, 0 );
    285  1.2  christos 		} else {
    286  1.2  christos 			unsigned ulevel;
    287  1.2  christos 
    288  1.2  christos 			rc = lutil_atoux( &ulevel, arg, 0 );
    289  1.2  christos 			level = (int)ulevel;
    290  1.2  christos 		}
    291  1.2  christos 
    292  1.2  christos 		if ( rc ) {
    293  1.1     lukem 			fprintf( stderr,
    294  1.1     lukem 				"unrecognized log level "
    295  1.1     lukem 				"\"%s\"\n", arg );
    296  1.1     lukem 			return 1;
    297  1.1     lukem 		}
    298  1.1     lukem 
    299  1.1     lukem 		if ( level == 0 ) {
    300  1.1     lukem 			*levelp = 0;
    301  1.1     lukem 
    302  1.1     lukem 		} else {
    303  1.1     lukem 			*levelp |= level;
    304  1.1     lukem 		}
    305  1.1     lukem 	}
    306  1.1     lukem 
    307  1.1     lukem 	return 0;
    308  1.1     lukem }
    309  1.1     lukem 
    310  1.1     lukem static void
    311  1.1     lukem usage( char *name )
    312  1.1     lukem {
    313  1.1     lukem 	fprintf( stderr,
    314  1.1     lukem 		"usage: %s options\n", name );
    315  1.1     lukem 	fprintf( stderr,
    316  1.1     lukem 		"\t-4\t\tIPv4 only\n"
    317  1.1     lukem 		"\t-6\t\tIPv6 only\n"
    318  1.1     lukem 		"\t-T {acl|add|auth|cat|dn|index|passwd|test}\n"
    319  1.1     lukem 		"\t\t\tRun in Tool mode\n"
    320  1.1     lukem 		"\t-c cookie\tSync cookie of consumer\n"
    321  1.1     lukem 		"\t-d level\tDebug level" "\n"
    322  1.1     lukem 		"\t-f filename\tConfiguration file\n"
    323  1.1     lukem 		"\t-F dir\tConfiguration directory\n"
    324  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    325  1.1     lukem 		"\t-g group\tGroup (id or name) to run as\n"
    326  1.1     lukem #endif
    327  1.1     lukem 		"\t-h URLs\t\tList of URLs to serve\n"
    328  1.1     lukem #ifdef SLAP_DEFAULT_SYSLOG_USER
    329  1.1     lukem 		"\t-l facility\tSyslog facility (default: LOCAL4)\n"
    330  1.1     lukem #endif
    331  1.1     lukem 		"\t-n serverName\tService name\n"
    332  1.1     lukem 		"\t-o <opt>[=val] generic means to specify options" );
    333  1.1     lukem 	if ( !BER_BVISNULL( &option_helpers[0].oh_name ) ) {
    334  1.1     lukem 		int	i;
    335  1.1     lukem 
    336  1.1     lukem 		fprintf( stderr, "; supported options:\n" );
    337  1.1     lukem 		for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++) {
    338  1.1     lukem 			fprintf( stderr, "\t\t%s\n", option_helpers[i].oh_usage );
    339  1.1     lukem 		}
    340  1.1     lukem 	} else {
    341  1.1     lukem 		fprintf( stderr, "\n" );
    342  1.1     lukem 	}
    343  1.1     lukem 	fprintf( stderr,
    344  1.1     lukem #ifdef HAVE_CHROOT
    345  1.1     lukem 		"\t-r directory\tSandbox directory to chroot to\n"
    346  1.1     lukem #endif
    347  1.1     lukem 		"\t-s level\tSyslog level\n"
    348  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    349  1.1     lukem 		"\t-u user\t\tUser (id or name) to run as\n"
    350  1.1     lukem #endif
    351  1.2  christos 		"\t-V\t\tprint version info (-VV exit afterwards, -VVV print\n"
    352  1.2  christos 		"\t\t\tinfo about static overlays and backends)\n"
    353  1.1     lukem     );
    354  1.1     lukem }
    355  1.1     lukem 
    356  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    357  1.1     lukem void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
    358  1.1     lukem #else
    359  1.1     lukem int main( int argc, char **argv )
    360  1.1     lukem #endif
    361  1.1     lukem {
    362  1.1     lukem 	int		i, no_detach = 0;
    363  1.1     lukem 	int		rc = 1;
    364  1.1     lukem 	char *urls = NULL;
    365  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    366  1.1     lukem 	char *username = NULL;
    367  1.1     lukem 	char *groupname = NULL;
    368  1.1     lukem #endif
    369  1.1     lukem #if defined(HAVE_CHROOT)
    370  1.1     lukem 	char *sandbox = NULL;
    371  1.1     lukem #endif
    372  1.1     lukem #ifdef SLAP_DEFAULT_SYSLOG_USER
    373  1.1     lukem 	int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
    374  1.1     lukem #endif
    375  1.1     lukem 
    376  1.2  christos #ifndef HAVE_WINSOCK
    377  1.2  christos 	int pid, waitfds[2];
    378  1.2  christos #endif
    379  1.1     lukem 	int g_argc = argc;
    380  1.1     lukem 	char **g_argv = argv;
    381  1.1     lukem 
    382  1.1     lukem 	char *configfile = NULL;
    383  1.1     lukem 	char *configdir = NULL;
    384  1.1     lukem 	char *serverName;
    385  1.1     lukem 	int serverMode = SLAP_SERVER_MODE;
    386  1.1     lukem 
    387  1.1     lukem 	struct sync_cookie *scp = NULL;
    388  1.1     lukem 	struct sync_cookie *scp_entry = NULL;
    389  1.1     lukem 
    390  1.1     lukem 	char **debug_unknowns = NULL;
    391  1.1     lukem 	char **syslog_unknowns = NULL;
    392  1.1     lukem 
    393  1.1     lukem 	char *serverNamePrefix = "";
    394  1.1     lukem 	size_t	l;
    395  1.1     lukem 
    396  1.1     lukem 	int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0;
    397  1.1     lukem 	int firstopt = 1;
    398  1.1     lukem 
    399  1.1     lukem #ifdef CSRIMALLOC
    400  1.1     lukem 	FILE *leakfile;
    401  1.1     lukem 	if( ( leakfile = fopen( "slapd.leak", "w" )) == NULL ) {
    402  1.1     lukem 		leakfile = stderr;
    403  1.1     lukem 	}
    404  1.1     lukem #endif
    405  1.1     lukem 
    406  1.1     lukem 	slap_sl_mem_init();
    407  1.1     lukem 
    408  1.2  christos 
    409  1.1     lukem 	(void) ldap_pvt_thread_initialize();
    410  1.1     lukem 
    411  1.1     lukem 	serverName = lutil_progname( "slapd", argc, argv );
    412  1.1     lukem 
    413  1.1     lukem 	if ( strcmp( serverName, "slapd" ) ) {
    414  1.2  christos #ifdef DEBUG_CLOSE
    415  1.2  christos 		extern void slapd_debug_close();
    416  1.2  christos 		slapd_debug_close();
    417  1.2  christos #endif
    418  1.1     lukem 		for (i=0; tools[i].name; i++) {
    419  1.1     lukem 			if ( !strcmp( serverName, tools[i].name ) ) {
    420  1.1     lukem 				rc = tools[i].func(argc, argv);
    421  1.1     lukem 				MAIN_RETURN(rc);
    422  1.1     lukem 			}
    423  1.1     lukem 		}
    424  1.1     lukem 	}
    425  1.1     lukem 
    426  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
    427  1.1     lukem 	{
    428  1.1     lukem 		int *ip;
    429  1.1     lukem 		char *newConfigFile;
    430  1.1     lukem 		char *newConfigDir;
    431  1.1     lukem 		char *newUrls;
    432  1.1     lukem 		char *regService = NULL;
    433  1.1     lukem 
    434  1.1     lukem 		if ( is_NT_Service ) {
    435  1.1     lukem 			lutil_CommenceStartupProcessing( serverName, slap_sig_shutdown );
    436  1.1     lukem 			if ( strcmp(serverName, SERVICE_NAME) )
    437  1.1     lukem 			    regService = serverName;
    438  1.1     lukem 		}
    439  1.1     lukem 
    440  1.1     lukem 		ip = (int*)lutil_getRegParam( regService, "DebugLevel" );
    441  1.1     lukem 		if ( ip != NULL ) {
    442  1.1     lukem 			slap_debug = *ip;
    443  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
    444  1.1     lukem 				"new debug level from registry is: %d\n", slap_debug, 0, 0 );
    445  1.1     lukem 		}
    446  1.1     lukem 
    447  1.1     lukem 		newUrls = (char *) lutil_getRegParam(regService, "Urls");
    448  1.1     lukem 		if (newUrls) {
    449  1.1     lukem 		    if (urls)
    450  1.1     lukem 			ch_free(urls);
    451  1.1     lukem 
    452  1.1     lukem 		    urls = ch_strdup(newUrls);
    453  1.1     lukem 		    Debug(LDAP_DEBUG_ANY, "new urls from registry: %s\n",
    454  1.1     lukem 				urls, 0, 0);
    455  1.1     lukem 		}
    456  1.1     lukem 
    457  1.1     lukem 		newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
    458  1.1     lukem 		if ( newConfigFile != NULL ) {
    459  1.2  christos 			configfile = ch_strdup(newConfigFile);
    460  1.1     lukem 			Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 );
    461  1.1     lukem 		}
    462  1.1     lukem 
    463  1.1     lukem 		newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" );
    464  1.1     lukem 		if ( newConfigDir != NULL ) {
    465  1.2  christos 			configdir = ch_strdup(newConfigDir);
    466  1.1     lukem 			Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir, 0, 0 );
    467  1.1     lukem 		}
    468  1.1     lukem 	}
    469  1.1     lukem #endif
    470  1.1     lukem 
    471  1.1     lukem 	while ( (i = getopt( argc, argv,
    472  1.1     lukem 			     "c:d:f:F:h:n:o:s:tT:V"
    473  1.1     lukem #ifdef LDAP_PF_INET6
    474  1.1     lukem 				"46"
    475  1.1     lukem #endif
    476  1.1     lukem #ifdef HAVE_CHROOT
    477  1.1     lukem 				"r:"
    478  1.1     lukem #endif
    479  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    480  1.1     lukem 				"S:"
    481  1.1     lukem #ifdef LOG_LOCAL4
    482  1.1     lukem 				"l:"
    483  1.1     lukem #endif
    484  1.1     lukem #endif
    485  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    486  1.1     lukem 				"u:g:"
    487  1.1     lukem #endif
    488  1.1     lukem 			     )) != EOF ) {
    489  1.1     lukem 		switch ( i ) {
    490  1.1     lukem #ifdef LDAP_PF_INET6
    491  1.1     lukem 		case '4':
    492  1.1     lukem 			slap_inet4or6 = AF_INET;
    493  1.1     lukem 			break;
    494  1.1     lukem 		case '6':
    495  1.1     lukem 			slap_inet4or6 = AF_INET6;
    496  1.1     lukem 			break;
    497  1.1     lukem #endif
    498  1.1     lukem 
    499  1.1     lukem 		case 'h':	/* listen URLs */
    500  1.1     lukem 			if ( urls != NULL ) free( urls );
    501  1.1     lukem 			urls = ch_strdup( optarg );
    502  1.1     lukem 			break;
    503  1.1     lukem 
    504  1.1     lukem 		case 'c':	/* provide sync cookie, override if exist in replica */
    505  1.1     lukem 			scp = (struct sync_cookie *) ch_calloc( 1,
    506  1.1     lukem 										sizeof( struct sync_cookie ));
    507  1.1     lukem 			ber_str2bv( optarg, 0, 1, &scp->octet_str );
    508  1.1     lukem 
    509  1.1     lukem 			/* This only parses out the rid at this point */
    510  1.1     lukem 			slap_parse_sync_cookie( scp, NULL );
    511  1.1     lukem 
    512  1.1     lukem 			if ( scp->rid == -1 ) {
    513  1.1     lukem 				Debug( LDAP_DEBUG_ANY,
    514  1.1     lukem 						"main: invalid cookie \"%s\"\n",
    515  1.1     lukem 						optarg, 0, 0 );
    516  1.1     lukem 				slap_sync_cookie_free( scp, 1 );
    517  1.1     lukem 				goto destroy;
    518  1.1     lukem 			}
    519  1.1     lukem 
    520  1.1     lukem 			LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) {
    521  1.1     lukem 				if ( scp->rid == scp_entry->rid ) {
    522  1.1     lukem 					Debug( LDAP_DEBUG_ANY,
    523  1.1     lukem 						    "main: duplicated replica id in cookies\n",
    524  1.1     lukem 							0, 0, 0 );
    525  1.1     lukem 					slap_sync_cookie_free( scp, 1 );
    526  1.1     lukem 					goto destroy;
    527  1.1     lukem 				}
    528  1.1     lukem 			}
    529  1.1     lukem 			LDAP_STAILQ_INSERT_TAIL( &slap_sync_cookie, scp, sc_next );
    530  1.1     lukem 			break;
    531  1.1     lukem 
    532  1.1     lukem 		case 'd': {	/* set debug level and 'do not detach' flag */
    533  1.1     lukem 			int	level = 0;
    534  1.1     lukem 
    535  1.1     lukem 			if ( strcmp( optarg, "?" ) == 0 ) {
    536  1.1     lukem 				check |= CHECK_LOGLEVEL;
    537  1.1     lukem 				break;
    538  1.1     lukem 			}
    539  1.1     lukem 
    540  1.1     lukem 			no_detach = 1;
    541  1.1     lukem 			if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) {
    542  1.1     lukem 				goto destroy;
    543  1.1     lukem 			}
    544  1.1     lukem #ifdef LDAP_DEBUG
    545  1.1     lukem 			slap_debug |= level;
    546  1.1     lukem #else
    547  1.1     lukem 			if ( level != 0 )
    548  1.1     lukem 				fputs( "must compile with LDAP_DEBUG for debugging\n",
    549  1.1     lukem 				       stderr );
    550  1.1     lukem #endif
    551  1.1     lukem 			} break;
    552  1.1     lukem 
    553  1.1     lukem 		case 'f':	/* read config file */
    554  1.1     lukem 			configfile = ch_strdup( optarg );
    555  1.1     lukem 			break;
    556  1.1     lukem 
    557  1.1     lukem 		case 'F':	/* use config dir */
    558  1.1     lukem 			configdir = ch_strdup( optarg );
    559  1.1     lukem 			break;
    560  1.1     lukem 
    561  1.1     lukem 		case 'o': {
    562  1.1     lukem 			char		*val = strchr( optarg, '=' );
    563  1.1     lukem 			struct berval	opt;
    564  1.1     lukem 
    565  1.1     lukem 			opt.bv_val = optarg;
    566  1.1     lukem 
    567  1.1     lukem 			if ( val ) {
    568  1.1     lukem 				opt.bv_len = ( val - optarg );
    569  1.1     lukem 				val++;
    570  1.1     lukem 
    571  1.1     lukem 			} else {
    572  1.1     lukem 				opt.bv_len = strlen( optarg );
    573  1.1     lukem 			}
    574  1.1     lukem 
    575  1.1     lukem 			for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++ ) {
    576  1.1     lukem 				if ( ber_bvstrcasecmp( &option_helpers[i].oh_name, &opt ) == 0 ) {
    577  1.1     lukem 					assert( option_helpers[i].oh_fnc != NULL );
    578  1.1     lukem 					if ( (*option_helpers[i].oh_fnc)( val, option_helpers[i].oh_arg ) == -1 ) {
    579  1.1     lukem 						/* we assume the option parsing helper
    580  1.1     lukem 						 * issues appropriate and self-explanatory
    581  1.1     lukem 						 * error messages... */
    582  1.1     lukem 						goto stop;
    583  1.1     lukem 					}
    584  1.1     lukem 					break;
    585  1.1     lukem 				}
    586  1.1     lukem 			}
    587  1.1     lukem 
    588  1.1     lukem 			if ( BER_BVISNULL( &option_helpers[i].oh_name ) ) {
    589  1.1     lukem 				goto unhandled_option;
    590  1.1     lukem 			}
    591  1.1     lukem 			break;
    592  1.1     lukem 		}
    593  1.1     lukem 
    594  1.1     lukem 		case 's':	/* set syslog level */
    595  1.1     lukem 			if ( strcmp( optarg, "?" ) == 0 ) {
    596  1.1     lukem 				check |= CHECK_LOGLEVEL;
    597  1.1     lukem 				break;
    598  1.1     lukem 			}
    599  1.1     lukem 
    600  1.1     lukem 			if ( parse_debug_level( optarg, &ldap_syslog, &syslog_unknowns ) ) {
    601  1.1     lukem 				goto destroy;
    602  1.1     lukem 			}
    603  1.1     lukem 			break;
    604  1.1     lukem 
    605  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    606  1.1     lukem 		case 'S':
    607  1.1     lukem 			if ( parse_syslog_level( optarg, &ldap_syslog_level ) ) {
    608  1.1     lukem 				goto destroy;
    609  1.1     lukem 			}
    610  1.1     lukem 			break;
    611  1.1     lukem 
    612  1.1     lukem #ifdef LOG_LOCAL4
    613  1.1     lukem 		case 'l':	/* set syslog local user */
    614  1.1     lukem 			if ( parse_syslog_user( optarg, &syslogUser ) ) {
    615  1.1     lukem 				goto destroy;
    616  1.1     lukem 			}
    617  1.1     lukem 			break;
    618  1.1     lukem #endif
    619  1.1     lukem #endif /* LDAP_DEBUG && LDAP_SYSLOG */
    620  1.1     lukem 
    621  1.1     lukem #ifdef HAVE_CHROOT
    622  1.1     lukem 		case 'r':
    623  1.1     lukem 			if( sandbox ) free(sandbox);
    624  1.1     lukem 			sandbox = ch_strdup( optarg );
    625  1.1     lukem 			break;
    626  1.1     lukem #endif
    627  1.1     lukem 
    628  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    629  1.1     lukem 		case 'u':	/* user name */
    630  1.1     lukem 			if( username ) free(username);
    631  1.1     lukem 			username = ch_strdup( optarg );
    632  1.1     lukem 			break;
    633  1.1     lukem 
    634  1.1     lukem 		case 'g':	/* group name */
    635  1.1     lukem 			if( groupname ) free(groupname);
    636  1.1     lukem 			groupname = ch_strdup( optarg );
    637  1.1     lukem 			break;
    638  1.1     lukem #endif /* SETUID && GETUID */
    639  1.1     lukem 
    640  1.1     lukem 		case 'n':  /* NT service name */
    641  1.1     lukem 			serverName = ch_strdup( optarg );
    642  1.1     lukem 			break;
    643  1.1     lukem 
    644  1.1     lukem 		case 't':
    645  1.1     lukem 			/* deprecated; use slaptest instead */
    646  1.1     lukem 			fprintf( stderr, "option -t deprecated; "
    647  1.1     lukem 				"use slaptest command instead\n" );
    648  1.1     lukem 			check |= CHECK_CONFIG;
    649  1.1     lukem 			break;
    650  1.1     lukem 
    651  1.1     lukem 		case 'V':
    652  1.1     lukem 			version++;
    653  1.1     lukem 			break;
    654  1.1     lukem 
    655  1.1     lukem 		case 'T':
    656  1.1     lukem 			if ( firstopt == 0 ) {
    657  1.1     lukem 				fprintf( stderr, "warning: \"-T %s\" "
    658  1.1     lukem 					"should be the first option.\n",
    659  1.1     lukem 					optarg );
    660  1.1     lukem 			}
    661  1.1     lukem 
    662  1.2  christos #ifdef DEBUG_CLOSE
    663  1.2  christos 			extern void slapd_debug_close();
    664  1.2  christos 			slapd_debug_close();
    665  1.2  christos #endif
    666  1.1     lukem 			/* try full option string first */
    667  1.1     lukem 			for ( i = 0; tools[i].name; i++ ) {
    668  1.1     lukem 				if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) {
    669  1.1     lukem 					rc = tools[i].func( argc, argv );
    670  1.1     lukem 					MAIN_RETURN( rc );
    671  1.1     lukem 				}
    672  1.1     lukem 			}
    673  1.1     lukem 
    674  1.1     lukem 			/* try bits of option string (backward compatibility for single char) */
    675  1.1     lukem 			l = strlen( optarg );
    676  1.1     lukem 			for ( i = 0; tools[i].name; i++ ) {
    677  1.1     lukem 				if ( strncmp( optarg, &tools[i].name[4], l ) == 0 ) {
    678  1.1     lukem 					rc = tools[i].func( argc, argv );
    679  1.1     lukem 					MAIN_RETURN( rc );
    680  1.1     lukem 				}
    681  1.1     lukem 			}
    682  1.1     lukem 
    683  1.1     lukem 			/* issue error */
    684  1.1     lukem 			serverName = optarg;
    685  1.1     lukem 			serverNamePrefix = "slap";
    686  1.1     lukem 			fprintf( stderr, "program name \"%s%s\" unrecognized; "
    687  1.1     lukem 					"aborting...\n", serverNamePrefix, serverName );
    688  1.1     lukem 			/* FALLTHRU */
    689  1.1     lukem 		default:
    690  1.1     lukem unhandled_option:;
    691  1.1     lukem 			usage( argv[0] );
    692  1.1     lukem 			rc = 1;
    693  1.1     lukem 			SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
    694  1.1     lukem 			goto stop;
    695  1.1     lukem 		}
    696  1.1     lukem 
    697  1.1     lukem 		if ( firstopt ) {
    698  1.1     lukem 			firstopt = 0;
    699  1.1     lukem 		}
    700  1.1     lukem 	}
    701  1.1     lukem 
    702  1.2  christos 	if ( optind != argc )
    703  1.2  christos 		goto unhandled_option;
    704  1.2  christos 
    705  1.1     lukem 	ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
    706  1.1     lukem 	ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
    707  1.1     lukem 	ldif_debug = slap_debug;
    708  1.1     lukem 
    709  1.1     lukem 	if ( version ) {
    710  1.1     lukem 		fprintf( stderr, "%s\n", Versionstr );
    711  1.2  christos 		if ( version > 2 ) {
    712  1.2  christos 			if ( slap_oinfo[0].ov_type ) {
    713  1.2  christos 				fprintf( stderr, "Included static overlays:\n");
    714  1.2  christos 				for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) {
    715  1.2  christos 					fprintf( stderr, "    %s\n", slap_oinfo[i].ov_type );
    716  1.2  christos 				}
    717  1.2  christos 			}
    718  1.2  christos 			if ( slap_binfo[0].bi_type ) {
    719  1.2  christos 				fprintf( stderr, "Included static backends:\n");
    720  1.2  christos 				for ( i= 0 ; slap_binfo[i].bi_type; i++ ) {
    721  1.2  christos 					fprintf( stderr, "    %s\n", slap_binfo[i].bi_type );
    722  1.2  christos 				}
    723  1.2  christos 			}
    724  1.2  christos 		}
    725  1.2  christos 
    726  1.1     lukem 		if ( version > 1 ) goto stop;
    727  1.1     lukem 	}
    728  1.1     lukem 
    729  1.1     lukem #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
    730  1.1     lukem 	{
    731  1.1     lukem 		char *logName;
    732  1.1     lukem #ifdef HAVE_EBCDIC
    733  1.1     lukem 		logName = ch_strdup( serverName );
    734  1.1     lukem 		__atoe( logName );
    735  1.1     lukem #else
    736  1.1     lukem 		logName = serverName;
    737  1.1     lukem #endif
    738  1.1     lukem 
    739  1.1     lukem #ifdef LOG_LOCAL4
    740  1.1     lukem 		openlog( logName, OPENLOG_OPTIONS, syslogUser );
    741  1.1     lukem #elif defined LOG_DEBUG
    742  1.1     lukem 		openlog( logName, OPENLOG_OPTIONS );
    743  1.1     lukem #endif
    744  1.1     lukem #ifdef HAVE_EBCDIC
    745  1.1     lukem 		free( logName );
    746  1.1     lukem #endif
    747  1.1     lukem 	}
    748  1.1     lukem #endif /* LDAP_DEBUG && LDAP_SYSLOG */
    749  1.1     lukem 
    750  1.1     lukem 	Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 );
    751  1.1     lukem 
    752  1.1     lukem 	global_host = ldap_pvt_get_fqdn( NULL );
    753  1.2  christos 	ber_str2bv( global_host, 0, 0, &global_host_bv );
    754  1.1     lukem 
    755  1.1     lukem 	if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) {
    756  1.1     lukem 		rc = 1;
    757  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
    758  1.1     lukem 		goto stop;
    759  1.1     lukem 	}
    760  1.1     lukem 
    761  1.1     lukem #if defined(HAVE_CHROOT)
    762  1.1     lukem 	if ( sandbox ) {
    763  1.1     lukem 		if ( chdir( sandbox ) ) {
    764  1.1     lukem 			perror("chdir");
    765  1.1     lukem 			rc = 1;
    766  1.1     lukem 			goto stop;
    767  1.1     lukem 		}
    768  1.1     lukem 		if ( chroot( sandbox ) ) {
    769  1.1     lukem 			perror("chroot");
    770  1.1     lukem 			rc = 1;
    771  1.1     lukem 			goto stop;
    772  1.1     lukem 		}
    773  1.2  christos 		if ( chdir( "/" ) ) {
    774  1.2  christos 			perror("chdir");
    775  1.2  christos 			rc = 1;
    776  1.2  christos 			goto stop;
    777  1.2  christos 		}
    778  1.1     lukem 	}
    779  1.1     lukem #endif
    780  1.1     lukem 
    781  1.1     lukem #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
    782  1.1     lukem 	if ( username != NULL || groupname != NULL ) {
    783  1.1     lukem 		slap_init_user( username, groupname );
    784  1.1     lukem 	}
    785  1.1     lukem #endif
    786  1.1     lukem 
    787  1.1     lukem 	extops_init();
    788  1.1     lukem 	lutil_passwd_init();
    789  1.1     lukem 
    790  1.1     lukem #ifdef HAVE_TLS
    791  1.1     lukem 	rc = ldap_create( &slap_tls_ld );
    792  1.1     lukem 	if ( rc ) {
    793  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
    794  1.1     lukem 		goto destroy;
    795  1.1     lukem 	}
    796  1.1     lukem 	/* Library defaults to full certificate checking. This is correct when
    797  1.1     lukem 	 * a client is verifying a server because all servers should have a
    798  1.1     lukem 	 * valid cert. But few clients have valid certs, so we want our default
    799  1.1     lukem 	 * to be no checking. The config file can override this as usual.
    800  1.1     lukem 	 */
    801  1.1     lukem 	rc = LDAP_OPT_X_TLS_NEVER;
    802  1.1     lukem 	(void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc );
    803  1.1     lukem #endif
    804  1.1     lukem 
    805  1.1     lukem 	rc = slap_init( serverMode, serverName );
    806  1.1     lukem 	if ( rc ) {
    807  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
    808  1.1     lukem 		goto destroy;
    809  1.1     lukem 	}
    810  1.1     lukem 
    811  1.1     lukem 	if ( read_config( configfile, configdir ) != 0 ) {
    812  1.1     lukem 		rc = 1;
    813  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
    814  1.1     lukem 
    815  1.1     lukem 		if ( check & CHECK_CONFIG ) {
    816  1.1     lukem 			fprintf( stderr, "config check failed\n" );
    817  1.1     lukem 		}
    818  1.1     lukem 
    819  1.1     lukem 		goto destroy;
    820  1.1     lukem 	}
    821  1.1     lukem 
    822  1.1     lukem 	if ( debug_unknowns ) {
    823  1.1     lukem 		rc = parse_debug_unknowns( debug_unknowns, &slap_debug );
    824  1.1     lukem 		ldap_charray_free( debug_unknowns );
    825  1.1     lukem 		debug_unknowns = NULL;
    826  1.1     lukem 		if ( rc )
    827  1.1     lukem 			goto destroy;
    828  1.1     lukem 	}
    829  1.1     lukem 	if ( syslog_unknowns ) {
    830  1.1     lukem 		rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog );
    831  1.1     lukem 		ldap_charray_free( syslog_unknowns );
    832  1.1     lukem 		syslog_unknowns = NULL;
    833  1.1     lukem 		if ( rc )
    834  1.1     lukem 			goto destroy;
    835  1.1     lukem 	}
    836  1.1     lukem 
    837  1.1     lukem 	if ( check & CHECK_LOGLEVEL ) {
    838  1.1     lukem 		rc = 0;
    839  1.1     lukem 		goto destroy;
    840  1.1     lukem 	}
    841  1.1     lukem 
    842  1.1     lukem 	if ( check & CHECK_CONFIG ) {
    843  1.1     lukem 		fprintf( stderr, "config check succeeded\n" );
    844  1.1     lukem 
    845  1.1     lukem 		check &= ~CHECK_CONFIG;
    846  1.1     lukem 		if ( check == CHECK_NONE ) {
    847  1.1     lukem 			rc = 0;
    848  1.1     lukem 			goto destroy;
    849  1.1     lukem 		}
    850  1.1     lukem 	}
    851  1.1     lukem 
    852  1.2  christos 	if ( glue_sub_attach( 0 ) != 0 ) {
    853  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    854  1.1     lukem 		    "subordinate config error\n",
    855  1.1     lukem 		    0, 0, 0 );
    856  1.1     lukem 
    857  1.1     lukem 		goto destroy;
    858  1.1     lukem 	}
    859  1.1     lukem 
    860  1.1     lukem 	if ( slap_schema_check( ) != 0 ) {
    861  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    862  1.1     lukem 		    "schema prep error\n",
    863  1.1     lukem 		    0, 0, 0 );
    864  1.1     lukem 
    865  1.1     lukem 		goto destroy;
    866  1.1     lukem 	}
    867  1.1     lukem 
    868  1.1     lukem #ifdef HAVE_TLS
    869  1.1     lukem 	rc = ldap_pvt_tls_init();
    870  1.1     lukem 	if( rc != 0) {
    871  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
    872  1.1     lukem 		    "main: TLS init failed: %d\n",
    873  1.2  christos 		    rc, 0, 0 );
    874  1.1     lukem 		rc = 1;
    875  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
    876  1.1     lukem 		goto destroy;
    877  1.1     lukem 	}
    878  1.1     lukem 
    879  1.1     lukem 	{
    880  1.1     lukem 		int opt = 1;
    881  1.1     lukem 
    882  1.1     lukem 		/* Force new ctx to be created */
    883  1.1     lukem 		rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
    884  1.1     lukem 		if( rc == 0 ) {
    885  1.1     lukem 			/* The ctx's refcount is bumped up here */
    886  1.1     lukem 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
    887  1.1     lukem 			load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
    888  1.1     lukem 		} else if ( rc != LDAP_NOT_SUPPORTED ) {
    889  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
    890  1.1     lukem 			    "main: TLS init def ctx failed: %d\n",
    891  1.1     lukem 			    rc, 0, 0 );
    892  1.1     lukem 			rc = 1;
    893  1.1     lukem 			SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
    894  1.1     lukem 			goto destroy;
    895  1.1     lukem 		}
    896  1.1     lukem 	}
    897  1.1     lukem #endif
    898  1.1     lukem 
    899  1.1     lukem #ifdef HAVE_CYRUS_SASL
    900  1.1     lukem 	if( sasl_host == NULL ) {
    901  1.1     lukem 		sasl_host = ch_strdup( global_host );
    902  1.1     lukem 	}
    903  1.1     lukem #endif
    904  1.1     lukem 
    905  1.1     lukem 	(void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake );
    906  1.1     lukem 	(void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown );
    907  1.1     lukem 
    908  1.1     lukem #ifdef SIGPIPE
    909  1.1     lukem 	(void) SIGNAL( SIGPIPE, SIG_IGN );
    910  1.1     lukem #endif
    911  1.1     lukem #ifdef SIGHUP
    912  1.1     lukem 	(void) SIGNAL( SIGHUP, slap_sig_shutdown );
    913  1.1     lukem #endif
    914  1.1     lukem 	(void) SIGNAL( SIGINT, slap_sig_shutdown );
    915  1.1     lukem 	(void) SIGNAL( SIGTERM, slap_sig_shutdown );
    916  1.1     lukem #ifdef SIGTRAP
    917  1.1     lukem 	(void) SIGNAL( SIGTRAP, slap_sig_shutdown );
    918  1.1     lukem #endif
    919  1.1     lukem #ifdef LDAP_SIGCHLD
    920  1.1     lukem 	(void) SIGNAL( LDAP_SIGCHLD, wait4child );
    921  1.1     lukem #endif
    922  1.1     lukem #ifdef SIGBREAK
    923  1.1     lukem 	/* SIGBREAK is generated when Ctrl-Break is pressed. */
    924  1.1     lukem 	(void) SIGNAL( SIGBREAK, slap_sig_shutdown );
    925  1.1     lukem #endif
    926  1.1     lukem 
    927  1.1     lukem #ifndef HAVE_WINSOCK
    928  1.2  christos 	if ( !no_detach ) {
    929  1.2  christos 		if ( lutil_pair( waitfds ) < 0 ) {
    930  1.2  christos 			Debug( LDAP_DEBUG_ANY,
    931  1.2  christos 				"main: lutil_pair failed: %d\n",
    932  1.2  christos 				0, 0, 0 );
    933  1.2  christos 			rc = 1;
    934  1.2  christos 			goto destroy;
    935  1.2  christos 		}
    936  1.2  christos 		pid = lutil_detach( no_detach, 0 );
    937  1.2  christos 		if ( pid ) {
    938  1.2  christos 			char buf[4];
    939  1.2  christos 			rc = EXIT_SUCCESS;
    940  1.2  christos 			close( waitfds[1] );
    941  1.2  christos 			if ( read( waitfds[0], buf, 1 ) != 1 )
    942  1.2  christos 				rc = EXIT_FAILURE;
    943  1.2  christos 			_exit( rc );
    944  1.2  christos 		} else {
    945  1.2  christos 			close( waitfds[0] );
    946  1.2  christos 		}
    947  1.2  christos 	}
    948  1.1     lukem #endif /* HAVE_WINSOCK */
    949  1.1     lukem 
    950  1.1     lukem #ifdef CSRIMALLOC
    951  1.1     lukem 	mal_leaktrace(1);
    952  1.1     lukem #endif
    953  1.1     lukem 
    954  1.1     lukem 	if ( slapd_pid_file != NULL ) {
    955  1.1     lukem 		FILE *fp = fopen( slapd_pid_file, "w" );
    956  1.1     lukem 
    957  1.1     lukem 		if ( fp == NULL ) {
    958  1.1     lukem 			int save_errno = errno;
    959  1.1     lukem 
    960  1.1     lukem 			Debug( LDAP_DEBUG_ANY, "unable to open pid file "
    961  1.1     lukem 				"\"%s\": %d (%s)\n",
    962  1.1     lukem 				slapd_pid_file,
    963  1.1     lukem 				save_errno, strerror( save_errno ) );
    964  1.1     lukem 
    965  1.1     lukem 			free( slapd_pid_file );
    966  1.1     lukem 			slapd_pid_file = NULL;
    967  1.1     lukem 
    968  1.1     lukem 			rc = 1;
    969  1.1     lukem 			goto destroy;
    970  1.1     lukem 		}
    971  1.1     lukem 		fprintf( fp, "%d\n", (int) getpid() );
    972  1.1     lukem 		fclose( fp );
    973  1.1     lukem 		slapd_pid_file_unlink = 1;
    974  1.1     lukem 	}
    975  1.1     lukem 
    976  1.1     lukem 	if ( slapd_args_file != NULL ) {
    977  1.1     lukem 		FILE *fp = fopen( slapd_args_file, "w" );
    978  1.1     lukem 
    979  1.1     lukem 		if ( fp == NULL ) {
    980  1.1     lukem 			int save_errno = errno;
    981  1.1     lukem 
    982  1.1     lukem 			Debug( LDAP_DEBUG_ANY, "unable to open args file "
    983  1.1     lukem 				"\"%s\": %d (%s)\n",
    984  1.1     lukem 				slapd_args_file,
    985  1.1     lukem 				save_errno, strerror( save_errno ) );
    986  1.1     lukem 
    987  1.1     lukem 			free( slapd_args_file );
    988  1.1     lukem 			slapd_args_file = NULL;
    989  1.1     lukem 
    990  1.1     lukem 			rc = 1;
    991  1.1     lukem 			goto destroy;
    992  1.1     lukem 		}
    993  1.1     lukem 
    994  1.1     lukem 		for ( i = 0; i < g_argc; i++ ) {
    995  1.1     lukem 			fprintf( fp, "%s ", g_argv[i] );
    996  1.1     lukem 		}
    997  1.1     lukem 		fprintf( fp, "\n" );
    998  1.1     lukem 		fclose( fp );
    999  1.1     lukem 		slapd_args_file_unlink = 1;
   1000  1.1     lukem 	}
   1001  1.1     lukem 
   1002  1.1     lukem 	/*
   1003  1.1     lukem 	 * FIXME: moved here from slapd_daemon_task()
   1004  1.1     lukem 	 * because back-monitor db_open() needs it
   1005  1.1     lukem 	 */
   1006  1.1     lukem 	time( &starttime );
   1007  1.1     lukem 
   1008  1.2  christos 	connections_init();
   1009  1.2  christos 
   1010  1.1     lukem 	if ( slap_startup( NULL ) != 0 ) {
   1011  1.1     lukem 		rc = 1;
   1012  1.1     lukem 		SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
   1013  1.1     lukem 		goto shutdown;
   1014  1.1     lukem 	}
   1015  1.1     lukem 
   1016  1.1     lukem 	Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
   1017  1.1     lukem 
   1018  1.2  christos #ifndef HAVE_WINSOCK
   1019  1.2  christos 	if ( !no_detach ) {
   1020  1.2  christos 		write( waitfds[1], "1", 1 );
   1021  1.2  christos 		close( waitfds[1] );
   1022  1.2  christos 	}
   1023  1.2  christos #endif
   1024  1.2  christos 
   1025  1.1     lukem #ifdef HAVE_NT_EVENT_LOG
   1026  1.1     lukem 	if (is_NT_Service)
   1027  1.1     lukem 	lutil_LogStartedEvent( serverName, slap_debug, configfile ?
   1028  1.1     lukem 		configfile : SLAPD_DEFAULT_CONFIGFILE , urls );
   1029  1.1     lukem #endif
   1030  1.1     lukem 
   1031  1.1     lukem 	rc = slapd_daemon();
   1032  1.1     lukem 
   1033  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
   1034  1.1     lukem 	/* Throw away the event that we used during the startup process. */
   1035  1.1     lukem 	if ( is_NT_Service )
   1036  1.1     lukem 		ldap_pvt_thread_cond_destroy( &started_event );
   1037  1.1     lukem #endif
   1038  1.1     lukem 
   1039  1.1     lukem shutdown:
   1040  1.1     lukem 	/* remember an error during shutdown */
   1041  1.1     lukem 	rc |= slap_shutdown( NULL );
   1042  1.1     lukem 
   1043  1.1     lukem destroy:
   1044  1.1     lukem 	if ( check & CHECK_LOGLEVEL ) {
   1045  1.1     lukem 		(void)loglevel_print( stdout );
   1046  1.1     lukem 	}
   1047  1.1     lukem 	/* remember an error during destroy */
   1048  1.1     lukem 	rc |= slap_destroy();
   1049  1.1     lukem 
   1050  1.1     lukem 	while ( !LDAP_STAILQ_EMPTY( &slap_sync_cookie )) {
   1051  1.1     lukem 		scp = LDAP_STAILQ_FIRST( &slap_sync_cookie );
   1052  1.1     lukem 		LDAP_STAILQ_REMOVE_HEAD( &slap_sync_cookie, sc_next );
   1053  1.1     lukem 		ch_free( scp );
   1054  1.1     lukem 	}
   1055  1.1     lukem 
   1056  1.1     lukem #ifdef SLAPD_MODULES
   1057  1.1     lukem 	module_kill();
   1058  1.1     lukem #endif
   1059  1.1     lukem 
   1060  1.1     lukem 	extops_kill();
   1061  1.1     lukem 
   1062  1.1     lukem 	supported_feature_destroy();
   1063  1.1     lukem 	entry_info_destroy();
   1064  1.1     lukem 
   1065  1.1     lukem stop:
   1066  1.1     lukem #ifdef HAVE_NT_EVENT_LOG
   1067  1.1     lukem 	if (is_NT_Service)
   1068  1.1     lukem 	lutil_LogStoppedEvent( serverName );
   1069  1.1     lukem #endif
   1070  1.1     lukem 
   1071  1.1     lukem 	Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
   1072  1.1     lukem 
   1073  1.1     lukem 
   1074  1.1     lukem #ifdef HAVE_NT_SERVICE_MANAGER
   1075  1.1     lukem 	lutil_ReportShutdownComplete();
   1076  1.1     lukem #endif
   1077  1.1     lukem 
   1078  1.1     lukem #ifdef LOG_DEBUG
   1079  1.1     lukem     closelog();
   1080  1.1     lukem #endif
   1081  1.1     lukem 	slapd_daemon_destroy();
   1082  1.1     lukem 
   1083  1.1     lukem 	controls_destroy();
   1084  1.1     lukem 
   1085  1.1     lukem 	filter_destroy();
   1086  1.1     lukem 
   1087  1.1     lukem 	schema_destroy();
   1088  1.1     lukem 
   1089  1.1     lukem 	lutil_passwd_destroy();
   1090  1.1     lukem 
   1091  1.1     lukem #ifdef HAVE_TLS
   1092  1.1     lukem 	if ( slap_tls_ld ) {
   1093  1.1     lukem 		ldap_pvt_tls_ctx_free( slap_tls_ctx );
   1094  1.1     lukem 		ldap_unbind_ext( slap_tls_ld, NULL, NULL );
   1095  1.1     lukem 	}
   1096  1.1     lukem 	ldap_pvt_tls_destroy();
   1097  1.1     lukem #endif
   1098  1.1     lukem 
   1099  1.1     lukem 	slap_sasl_regexp_destroy();
   1100  1.1     lukem 
   1101  1.1     lukem 	if ( slapd_pid_file_unlink ) {
   1102  1.1     lukem 		unlink( slapd_pid_file );
   1103  1.1     lukem 	}
   1104  1.1     lukem 	if ( slapd_args_file_unlink ) {
   1105  1.1     lukem 		unlink( slapd_args_file );
   1106  1.1     lukem 	}
   1107  1.1     lukem 
   1108  1.1     lukem 	config_destroy();
   1109  1.1     lukem 
   1110  1.1     lukem 	if ( configfile )
   1111  1.1     lukem 		ch_free( configfile );
   1112  1.1     lukem 	if ( configdir )
   1113  1.1     lukem 		ch_free( configdir );
   1114  1.1     lukem 	if ( urls )
   1115  1.1     lukem 		ch_free( urls );
   1116  1.2  christos 	if ( global_host )
   1117  1.2  christos 		ch_free( global_host );
   1118  1.1     lukem 
   1119  1.1     lukem 	/* kludge, get symbols referenced */
   1120  1.1     lukem 	tavl_free( NULL, NULL );
   1121  1.1     lukem 
   1122  1.1     lukem #ifdef CSRIMALLOC
   1123  1.1     lukem 	mal_dumpleaktrace( leakfile );
   1124  1.1     lukem #endif
   1125  1.1     lukem 
   1126  1.1     lukem 	MAIN_RETURN(rc);
   1127  1.1     lukem }
   1128  1.1     lukem 
   1129  1.1     lukem 
   1130  1.1     lukem #ifdef LDAP_SIGCHLD
   1131  1.1     lukem 
   1132  1.1     lukem /*
   1133  1.1     lukem  *  Catch and discard terminated child processes, to avoid zombies.
   1134  1.1     lukem  */
   1135  1.1     lukem 
   1136  1.1     lukem static RETSIGTYPE
   1137  1.1     lukem wait4child( int sig )
   1138  1.1     lukem {
   1139  1.1     lukem     int save_errno = errno;
   1140  1.1     lukem 
   1141  1.1     lukem #ifdef WNOHANG
   1142  1.2  christos     do
   1143  1.2  christos         errno = 0;
   1144  1.1     lukem #ifdef HAVE_WAITPID
   1145  1.2  christos     while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR );
   1146  1.1     lukem #else
   1147  1.2  christos     while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR );
   1148  1.1     lukem #endif
   1149  1.1     lukem #else
   1150  1.1     lukem     (void) wait( NULL );
   1151  1.1     lukem #endif
   1152  1.1     lukem     (void) SIGNAL_REINSTALL( sig, wait4child );
   1153  1.1     lukem     errno = save_errno;
   1154  1.1     lukem }
   1155  1.1     lukem 
   1156  1.1     lukem #endif /* LDAP_SIGCHLD */
   1157