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