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