summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/main.c')
-rw-r--r--ldap/servers/slapd/main.c2753
1 files changed, 2753 insertions, 0 deletions
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
new file mode 100644
index 00000000..b52df26d
--- /dev/null
+++ b/ldap/servers/slapd/main.c
@@ -0,0 +1,2753 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#if defined(NET_SSL)
+#include <ldap.h>
+#undef OFF
+#undef LITTLE_ENDIAN
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if !defined(_WIN32) && !defined(aix)
+#include <sys/fcntl.h>
+#else
+#include <fcntl.h>
+#endif
+#include <time.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <stdlib.h>
+#if defined( _WIN32 )
+#include "ntslapdmessages.h"
+#include "proto-ntutil.h"
+#else
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h> /* getpwnam */
+#if !defined(IRIX) && !defined(LINUX)
+union semun {
+ int val;
+ struct semid_ds *buf;
+ ushort *array;
+};
+#endif
+#endif
+#if !defined(_WIN32)
+#include <unistd.h> /* dup2 */
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/param.h> /* MAXPATHLEN */
+#endif
+#if defined(__sun)
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+#endif
+#include "slap.h"
+#include "slapi-plugin.h"
+#include "prinit.h"
+#include "snmp_collator.h"
+#include "fe.h" /* client_auth_init() */
+#include "protect_db.h"
+#include "getopt_ext.h"
+#include "fe.h"
+
+#ifndef LDAP_DONT_USE_SMARTHEAP
+#include "smrtheap.h"
+#endif
+
+#if defined( XP_WIN32 )
+void dostounixpath(char *szText);
+#endif
+
+/* Forward Declarations */
+static void register_objects();
+static void process_command_line(int argc, char **argv, char *myname, char **extraname);
+static int slapd_exemode_ldif2db();
+static int slapd_exemode_db2ldif(int argc, char **argv);
+static int slapd_exemode_db2index();
+static int slapd_exemode_archive2db();
+static int slapd_exemode_db2archive();
+#if defined(UPGRADEDB)
+static int slapd_exemode_upgradedb();
+#endif
+static int slapd_exemode_dbtest();
+static int slapd_exemode_suffix2instance();
+static int slapd_debug_level_string2level( const char *s );
+static void slapd_debug_level_log( int level );
+static void slapd_debug_level_usage( void );
+static void cmd_set_shutdown(int);
+/*
+ * global variables
+ */
+
+static int slapd_exemode = SLAPD_EXEMODE_UNKNOWN;
+
+static int init_cmd_shutdown_detect()
+{
+
+#ifndef _WIN32
+ /* First of all, we must reset the signal mask to get rid of any blockages
+ * the process may have inherited from its parent (such as the console), which
+ * might result in the process not delivering those blocked signals, and thus,
+ * misbehaving....
+ */
+ {
+ int rc;
+ sigset_t proc_mask;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "Reseting signal mask....\n", 0, 0, 0);
+ (void)sigemptyset( &proc_mask );
+ rc = pthread_sigmask( SIG_SETMASK, &proc_mask, NULL );
+ LDAPDebug( LDAP_DEBUG_TRACE, " %s \n",
+ rc ? "Failed to reset signal mask":"....Done (signal mask reset)!!", 0, 0 );
+ }
+#endif
+
+#if defined ( HPUX10 )
+ PR_CreateThread ( PR_USER_THREAD,
+ catch_signals,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ SLAPD_DEFAULT_THREAD_STACKSIZE);
+#elif defined ( HPUX11 )
+ /* In the optimized builds for HPUX, the signal handler doesn't seem
+ * to get set correctly unless the primordial thread gets a chance
+ * to run before we make the call to SIGNAL. (At this point the
+ * the primordial thread has spawned the daemon thread which called
+ * this function.) The call to DS_Sleep will give the primordial
+ * thread a chance to run. */
+ DS_Sleep(0);
+#endif
+#ifndef _WIN32
+ (void) SIGNAL( SIGPIPE, SIG_IGN );
+ (void) SIGNAL( SIGCHLD, slapd_wait4child );
+#ifndef LINUX
+ /* linux uses USR1/USR2 for thread synchronization, so we aren't
+ * allowed to mess with those.
+ */
+ (void) SIGNAL( SIGUSR1, slapd_do_nothing );
+ (void) SIGNAL( SIGUSR2, cmd_set_shutdown );
+#endif
+ (void) SIGNAL( SIGTERM, cmd_set_shutdown );
+ (void) SIGNAL( SIGHUP, cmd_set_shutdown );
+ (void) SIGNAL( SIGINT, cmd_set_shutdown );
+#endif /* _WIN32 */
+ return 0;
+}
+
+static void
+cmd_set_shutdown (int sig)
+{
+ /* don't log anything from a signal handler:
+ * you could be holding a lock when the signal was trapped. more
+ * specifically, you could be holding the logfile lock (and deadlock
+ * yourself).
+ */
+
+#if 0
+ LDAPDebug( LDAP_DEBUG_ANY, "slapd got shutdown signal\n", 0, 0, 0 );
+#endif
+ c_set_shutdown();
+#ifndef _WIN32
+#ifndef LINUX
+ /* don't mess with USR1/USR2 on linux, used by libpthread */
+ (void) SIGNAL( SIGUSR2, cmd_set_shutdown );
+#endif
+ (void) SIGNAL( SIGTERM, cmd_set_shutdown );
+ (void) SIGNAL( SIGHUP, cmd_set_shutdown );
+#endif
+}
+
+#ifdef HPUX10
+extern void collation_init();
+#endif
+
+#ifndef WIN32
+
+/* Changes the ownership of the given file/directory iff not
+ already the owner
+ Returns 0 upon success or non-zero otherwise, usually -1 if
+ some system error occurred
+*/
+static int
+chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
+{
+ struct stat statbuf;
+ int result = 1;
+ if (!filename)
+ return result;
+
+ memset(&statbuf, '\0', sizeof(statbuf));
+ if (!(result = stat(filename, &statbuf)))
+ {
+ if (((uid != -1) && (uid != statbuf.st_uid)) ||
+ ((gid != -1) && (gid != statbuf.st_gid)))
+ {
+ result = chown(filename, uid, gid);
+ }
+ }
+
+ return result;
+}
+
+/*
+ Four cases:
+ - change ownership of all files in directory (strip_fn=PR_FALSE)
+ - change ownership of all files in directory; but trailing fn needs to be stripped (strip_fn=PR_TRUE)
+ - fn is relative to root directory (/access); we print error message and let user shoot his foot
+ - fn is relative to current directory (access); we print error message and let user shoot his other foot
+
+ The docs say any valid filename.
+*/
+
+static void
+chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ char dirname[MAXPATHLEN + 1], file[MAXPATHLEN + 1];
+ char *log=NULL, *ptr=NULL;
+ int rc=0;
+
+ log=strdup(name);
+ if(strip_fn)
+ {
+ if((ptr=strrchr(log,'/'))==NULL)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of ./%s \n",name,0,0);
+ chown_if_not_owner(log, pw->pw_uid, -1 );
+ rc=1;
+ } else if(log==ptr) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of / directory and its contents to %s\n",pw->pw_name,0,0);
+ *(++ptr)='\0';
+ } else {
+ *ptr='\0';
+ }
+ }
+ if ((!rc) && ((dir = PR_OpenDir(log)) != NULL ))
+ {
+ /* change the owner for each of the files in the dir */
+ while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL )
+ {
+ sprintf(file,"%s/%s",log,entry->name);
+ chown_if_not_owner( file, pw->pw_uid, -1 );
+ }
+ PR_CloseDir( dir );
+ }
+ free(log);
+}
+
+/* Changes the owner of the files in the logs and
+ * config directorys to the user that the server runs as.
+*/
+
+static void
+fix_ownership()
+{
+ int len, n;
+ struct passwd* pw=NULL;
+ char dirname[MAXPATHLEN + 1];
+
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+
+ if ( slapdFrontendConfig->localuser != NULL ) {
+ if ( (pw = getpwnam( slapdFrontendConfig->localuser )) == NULL )
+ return;
+ }
+ else {
+ return;
+ }
+
+ /* The instance directory needs to be owned by the local user */
+ chown_if_not_owner( slapdFrontendConfig->instancedir, pw->pw_uid, -1 );
+ sprintf(dirname,"%s/config",slapdFrontendConfig->instancedir);
+ chown_dir_files(dirname, pw, PR_FALSE); /* config directory */
+ chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE); /* do access log directory */
+ chown_dir_files(slapdFrontendConfig->auditlog, pw, PR_TRUE); /* do audit log directory */
+ chown_dir_files(slapdFrontendConfig->errorlog, pw, PR_TRUE); /* do error log directory */
+
+}
+#endif
+
+/* Changes identity to the named user
+ * If username == NULL, does nothing.
+ * Does nothing on NT regardless.
+ */
+static int main_setuid(char *username)
+{
+#ifndef _WIN32
+ if (username != NULL) {
+ struct passwd *pw;
+ /* Make sure everything in the log and config directory
+ * is owned by the correct user */
+ fix_ownership();
+ pw = getpwnam (username);
+ if (pw == NULL) {
+ int oserr = errno;
+
+ LDAPDebug (LDAP_DEBUG_ANY, "getpwnam(%s) == NULL, error %d (%s)\n",
+ username, oserr, slapd_system_strerror(oserr));
+ } else {
+ if (setgid (pw->pw_gid) != 0) {
+ int oserr = errno;
+
+ LDAPDebug (LDAP_DEBUG_ANY, "setgid(%li) != 0, error %d (%s)\n",
+ (long)pw->pw_gid, oserr, slapd_system_strerror(oserr));
+ return -1;
+ }
+ if (setuid (pw->pw_uid) != 0) {
+ int oserr = errno;
+
+ LDAPDebug (LDAP_DEBUG_ANY, "setuid(%li) != 0, error %d (%s)\n",
+ (long)pw->pw_uid, oserr, slapd_system_strerror(oserr));
+ return -1;
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+/* set good defaults for front-end config in referral mode */
+static void referral_set_defaults(void)
+{
+#if !defined(_WIN32) && !defined(AIX)
+ char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
+ config_set_maxdescriptors( CONFIG_MAXDESCRIPTORS_ATTRIBUTE, "1024", errorbuf, 1);
+#endif
+}
+
+static int
+name2exemode( char *progname, char *s, int exit_if_unknown )
+{
+ int exemode;
+
+ if ( strcmp( s, "db2ldif" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_DB2LDIF;
+ } else if ( strcmp( s, "ldif2db" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_LDIF2DB;
+ } else if ( strcmp( s, "archive2db" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_ARCHIVE2DB;
+ } else if ( strcmp( s, "db2archive" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_DB2ARCHIVE;
+ } else if ( strcmp( s, "server" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_SLAPD;
+ } else if ( strcmp( s, "dbtest" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_DBTEST;
+ } else if ( strcmp( s, "db2index" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_DB2INDEX;
+ } else if ( strcmp( s, "refer" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_REFERRAL;
+ } else if ( strcmp( s, "suffix2instance" ) == 0 ) {
+ exemode = SLAPD_EXEMODE_SUFFIX2INSTANCE;
+ }
+#if defined(UPGRADEDB)
+ else if ( strcmp( s, "upgradedb" ) == 0 )
+ {
+ exemode = SLAPD_EXEMODE_UPGRADEDB;
+ }
+#endif
+ else if ( exit_if_unknown ) {
+ fprintf( stderr, "usage: %s -D instancedir "
+ "[ldif2db | db2ldif | archive2db "
+ "| db2archive | db2index | refer | suffix2instance"
+#if defined(UPGRADEDB)
+ " | upgradedb] "
+#else
+ "] "
+#endif
+ "[options]\n", progname );
+ exit( 1 );
+ } else {
+ exemode = SLAPD_EXEMODE_UNKNOWN;
+ }
+
+ return( exemode );
+}
+
+
+static void
+usage( char *name, char *extraname )
+{
+ char *usagestr = NULL;
+ char *extraspace;
+
+ if ( extraname == NULL ) {
+ extraspace = extraname = "";
+ } else {
+ extraspace = " ";
+ }
+
+ switch( slapd_exemode ) {
+ case SLAPD_EXEMODE_DB2LDIF:
+ usagestr = "usage: %s %s%s-D instancedir [-n backend-instance-name] [-d debuglevel] "
+ "[-N] [-a outputfile] [-r] [-C] [{-s includesuffix}*] "
+ "[{-x excludesuffix}*] [-u] [-U] [-m] [-M] [-E]\n"
+ "Note: either \"-n backend_instance_name\" or \"-s includesuffix\" is required.\n";
+ break;
+ case SLAPD_EXEMODE_LDIF2DB:
+ usagestr = "usage: %s %s%s-D instancedir [-d debuglevel] "
+ "[-n backend_instance_name] [-O] [-g uniqueid_type] [--namespaceid uniqueID]"
+ "[{-s includesuffix}*] [{-x excludesuffix}*] [-E] {-i ldif-file}*\n"
+ "Note: either \"-n backend_instance_name\" or \"-s includesuffix\" is required.\n";
+ break;
+ case SLAPD_EXEMODE_DB2ARCHIVE:
+ usagestr = "usage: %s %s%s-D instancedir [-d debuglevel] -a archivedir\n";
+ break;
+ case SLAPD_EXEMODE_ARCHIVE2DB:
+ usagestr = "usage: %s %s%s-D instancedir [-d debuglevel] -a archivedir\n";
+ break;
+ case SLAPD_EXEMODE_DB2INDEX:
+ usagestr = "usage: %s %s%s-D instancedir -n backend-instance-name "
+ "[-d debuglevel] {-t attributetype}* {-T VLV Search Name}*\n";
+ /* JCM should say 'Address Book' or something instead of VLV */
+ break;
+ case SLAPD_EXEMODE_REFERRAL:
+ usagestr = "usage: %s %s%s-D instancedir -r referral-url [-p port]\n";
+ break;
+ case SLAPD_EXEMODE_DBTEST:
+ usagestr = "usage: %s %s%s-D instancedir -n backend-instance-name "
+ "[-d debuglevel] [-S] [-v]\n";
+ break;
+ case SLAPD_EXEMODE_SUFFIX2INSTANCE:
+ usagestr = "usage: %s %s%s -D instancedir {-s suffix}*\n";
+ break;
+#if defined(UPGRADEDB)
+ case SLAPD_EXEMODE_UPGRADEDB:
+ usagestr = "usage: %s %s%s-D instancedir [-d debuglevel] [-f] -a archivedir\n";
+ break;
+#endif
+
+ default: /* SLAPD_EXEMODE_SLAPD */
+ usagestr = "usage: %s %s%s-D instancedir [-d debuglevel] "
+ "[-i pidlogfile] [-v] [-V]\n";
+ }
+
+ fprintf( stderr, usagestr, name, extraname, extraspace );
+}
+
+
+/*
+ * These nasty globals are the settings collected from the
+ * command line by the process_command_line function. The
+ * various slapd_exemode functions read these to drive their
+ * execution.
+ */
+static char *extraname;
+static char *myname;
+static int n_port = 0;
+static int s_port = 0;
+static char **ldif_file = NULL;
+static int ldif_files = 0;
+static int ldif_backend = 0;
+static char *cmd_line_instance_name = NULL;
+static char **cmd_line_instance_names = NULL;
+static int skip_db_protect_check = 0;
+static char **db2ldif_include = NULL;
+static char **db2ldif_exclude = NULL;
+static int ldif2db_removedupvals = 1;
+static int ldif2db_noattrindexes = 0;
+static char **db2index_attrs = NULL;
+static int ldif_printkey = EXPORT_PRINTKEY|EXPORT_APPENDMODE;
+static char *archive_name = NULL;
+static int db2ldif_dump_replica = 0;
+static int db2ldif_dump_uniqueid = 1;
+static int ldif2db_generate_uniqueid = SLAPI_UNIQUEID_GENERATE_TIME_BASED;
+static int ldif2db_load_state= 1;
+static char *ldif2db_namespaceid = NULL;
+int importexport_encrypt = 0;
+#if defined(UPGRADEDB)
+static int upgradedb_force = 0;
+#endif
+
+/* taken from idsktune */
+#if defined(__sun)
+static void ids_get_platform_solaris(char *buf)
+{
+ struct utsname u;
+ char sbuf[128];
+ FILE *fp;
+
+#if defined(sparc) || defined(__sparc)
+ int is_u = 0;
+
+ sbuf[0] = '\0';
+ sysinfo(SI_MACHINE,sbuf,128);
+
+ if (strcmp(sbuf,"sun4u") == 0) {
+ is_u = 1;
+ }
+
+ sbuf[0] = '\0';
+ sysinfo(SI_PLATFORM,sbuf,128);
+
+ sprintf(buf,"%ssparc%s-%s-solaris",
+ is_u ? "u" : "",
+ sizeof(long) == 4 ? "" : "v9",
+ sbuf);
+#else
+#if defined(i386) || defined(__i386)
+ sprintf(buf,"i386-unknown-solaris");
+#else
+ sprintf(buf,"unknown-unknown-solaris");
+#endif /* not i386 */
+#endif /* not sparc */
+
+ uname(&u);
+ if (isascii(u.release[0]) && isdigit(u.release[0])) strcat(buf,u.release);
+
+ fp = fopen("/etc/release","r");
+
+ if (fp != NULL) {
+ char *rp;
+
+ sbuf[0] = '\0';
+ fgets(sbuf,128,fp);
+ fclose(fp);
+ rp = strstr(sbuf,"Solaris");
+ if (rp) {
+ rp += 8;
+ while(*rp != 's' && *rp != '\0') rp++;
+ if (*rp == 's') {
+ char *rp2;
+ rp2 = strchr(rp,' ');
+ if (rp2) *rp2 = '\0';
+ strcat(buf,"_");
+ strcat(buf,rp);
+ }
+ }
+ }
+}
+#endif
+
+static void slapd_print_version(int verbose)
+{
+#if defined(__sun)
+ char buf[8192];
+#endif
+ char *versionstring = config_get_versionstring();
+ char *buildnum = config_get_buildnum();
+
+ printf( SLAPD_VENDOR_NAME "\n%s B%s\n", versionstring, buildnum);
+
+ /* not here in Win32 */
+#if !defined(_WIN32)
+ if (strcmp(buildnum,BUILD_NUM) != 0) {
+ printf( "ns-slapd: B%s\n", BUILD_NUM);
+ }
+#endif
+
+ slapi_ch_free( (void **)&versionstring);
+ slapi_ch_free( (void **)&buildnum);
+
+ if (verbose == 0) return;
+
+#if defined(__sun)
+ ids_get_platform_solaris(buf);
+ printf("System: %s\n",buf);
+#endif
+
+ /* this won't print much with the -v flag as the dse.ldif file
+ * hasn't be read yet.
+ */
+ plugin_print_versions();
+}
+
+#if defined( _WIN32 )
+/* On Windows, we signal the SCM when we're still starting up */
+static int
+write_start_pid_file()
+{
+ if( SlapdIsAService() )
+ {
+ /* Initialization complete and successful. Set service to running */
+ LDAPServerStatus.dwCurrentState = SERVICE_START_PENDING;
+ LDAPServerStatus.dwCheckPoint = 1;
+ LDAPServerStatus.dwWaitHint = 1000;
+
+ if (!SetServiceStatus(hLDAPServerServiceStatus, &LDAPServerStatus)) {
+ ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_START_FAILED, 1,
+ "Could not set Service status.");
+ exit(1);
+ }
+ }
+
+ ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_STARTED, 0, NULL );
+ return 0;
+}
+#else /* WIN32 */
+/* On UNIX, we create a file with our PID in it */
+static int
+write_start_pid_file()
+{
+ FILE *fp = NULL;
+ /*
+ * The following section of code is closely coupled with the
+ * admin programs. Please do not make changes here without
+ * consulting the start/stop code for the admin code.
+ */
+ if ( (fp = fopen( start_pid_file, "w" )) != NULL ) {
+ fprintf( fp, "%d\n", getpid() );
+ fclose( fp );
+ return 0;
+ } else
+ {
+ return -1;
+ }
+}
+#endif /* WIN32 */
+
+int
+main( int argc, char **argv)
+{
+ int return_value = 0;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ daemon_ports_t arg = {0};
+ Slapi_Backend *be = NULL;
+ int init_ssl;
+#ifndef __LP64__
+#if defined(__hpux)
+ /* for static constructors */
+ _main();
+#endif
+#endif
+ /*
+ * Initialize NSPR very early. NSPR supports implicit initialization,
+ * but it is not bulletproof -- so it is better to be explicit.
+ */
+ PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0 );
+ FrontendConfig_init();
+
+#ifdef _WIN32
+ /* Break into the debugger if DEBUG_BREAK is set in the environment
+ to "slapd" */
+ {
+ char *s = getenv( "DEBUG_BREAK" );
+ if ( (s != NULL) && !stricmp(s, "slapd") )
+ DebugBreak();
+ }
+
+ /* do module debug level init for slapd, and libslapd */
+ module_ldap_debug = &slapd_ldap_debug;
+ libldap_init_debug_level(&slapd_ldap_debug);
+
+ dostounixpath( argv[0] );
+ _strlwr( argv[0] );
+
+#else /* _WIN32 */
+ /* Pause for the debugger if DEBUG_SLEEP is set in the environment */
+ {
+ char *s = getenv( "DEBUG_SLEEP" );
+ if ( (s != NULL) && isdigit(*s) ) {
+ int secs = atoi(s);
+ printf("slapd pid is %d\n", getpid());
+ sleep(secs);
+ }
+ }
+
+
+/* used to set configfile to the default config file name here */
+
+#endif /* _WIN32 */
+
+ if ( (myname = strrchr( argv[0], '/' )) == NULL ) {
+ myname = slapi_ch_strdup( argv[0] );
+ } else {
+ myname = slapi_ch_strdup( myname + 1 );
+ }
+
+#if defined( XP_WIN32 )
+ /* Strip ".exe" if it's there */
+ {
+ char *pdot;
+ if ( (pdot = strrchr( myname, '.' )) != NULL ) {
+ *pdot = '\0';
+ }
+ }
+#endif
+
+ process_command_line(argc,argv,myname,&extraname);
+
+ if (!slapdFrontendConfig->instancedir ||
+ !slapdFrontendConfig->configdir) {
+ usage( myname, extraname );
+ exit( 1 );
+ }
+
+
+ /* display debugging level if it is anything other than the default */
+ if ( 0 != ( slapd_ldap_debug & ~LDAP_DEBUG_ANY )) {
+ slapd_debug_level_log( slapd_ldap_debug );
+ }
+
+#ifndef LDAP_DONT_USE_SMARTHEAP
+ MemRegisterTask();
+#endif
+
+ slapd_init();
+ g_log_init(1);
+ vattr_init();
+
+ if (slapd_exemode == SLAPD_EXEMODE_REFERRAL) {
+ /* make up the config stuff */
+ referral_set_defaults();
+ n_port = config_get_port();
+ s_port = config_get_secureport();
+ register_objects();
+
+ } else {
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ /* The 2 calls below have been moved to this place to make sure that they
+ * are called before setup_internal_backends to avoid bug 524439 */
+ /*
+ * The 2 calls below where being sometimes called AFTER ldapi_register_extended_op
+ * (such fact was being stated and reproducible for some optimized installations
+ * at startup (bug 524439)... Such bad call was happening in the context of
+ * setup_internal_backends -> dse_read_file -> load_plugin_entry ->
+ * plugin_setup -> replication_multimaster_plugin_init ->
+ * slapi_register_plugin -> plugin_setup -> multimaster_start_extop_init ->
+ * slapi_pblock_set -> ldapi_register_extended_op... Unfortunately, the server
+ * design is such that it is assumed that ldapi_init_extended_ops is always
+ * called first.
+ * THE FIX: Move the two calls below before a call to setup_internal_backends
+ * (down in this same function)
+ */
+ init_saslmechanisms();
+ ldapi_init_extended_ops();
+
+
+ /*
+ * Initialize the default backend. This should be done before we
+ * process the config. files
+ */
+ defbackend_init();
+
+ /*
+ * Register the extensible objects with the factory.
+ */
+ register_objects();
+ /*
+ * Register the controls that we support.
+ */
+ init_controls();
+
+ /*
+ * Process the config files.
+ */
+ if (0 == slapd_bootstrap_config(slapdFrontendConfig->configdir)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "startup",
+ "The configuration files in directory %s could not be read or were not found. Please refer to the error log or output for more information.\n",
+ slapdFrontendConfig->configdir);
+ exit(1);
+ }
+
+ /* -sduloutre: must be done before any internal search */
+ /* do it before splitting off to other modes too -robey */
+ /* -richm: must be done before reading config files */
+ if (0 != (return_value = compute_init())) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Initialization Failed 0 %d\n",return_value,0,0);
+ exit (1);
+ }
+ entry_computed_attr_init();
+
+ if (0 == setup_internal_backends(slapdFrontendConfig->configdir)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "startup",
+ "The configuration files in directory %s could not be read or were not found. Please refer to the error log or output for more information.\n",
+ slapdFrontendConfig->configdir);
+ exit(1);
+ }
+
+ n_port = config_get_port();
+ s_port = config_get_secureport();
+ }
+
+ raise_process_limits(); /* should be done ASAP once config file read */
+
+#ifdef PUMPKIN_HOUR
+ if ( time( NULL ) > (PUMPKIN_HOUR - 10) ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: ** This beta software has expired **\n", 0, 0, 0 );
+ exit( 1 );
+ }
+#endif
+
+ /* Set entry points in libslapd */
+ set_entry_points();
+
+ /*
+ * Initialise NSS once for the whole slapd process, whether SSL
+ * is enabled or not. We use NSS for random number generation and
+ * other things even if we are not going to accept SSL connections.
+ * We also need NSS for attribute encryption/decryption on import and export.
+ */
+ init_ssl = ( (slapd_exemode == SLAPD_EXEMODE_SLAPD) || importexport_encrypt)
+ && config_get_security()
+ && (0 != s_port) && (s_port <= LDAP_PORT_MAX);
+ /* As of DS 6.1, always do a full initialization so that other
+ * modules can assume NSS is available
+ */
+ if ( slapd_nss_init((slapd_exemode == SLAPD_EXEMODE_SLAPD),
+ (slapd_exemode != SLAPD_EXEMODE_REFERRAL) /* have config? */ )) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: NSS Initialization Failed.\n", 0, 0, 0);
+ exit (1);
+ }
+
+ if (slapd_exemode == SLAPD_EXEMODE_SLAPD) {
+ client_auth_init();
+ }
+
+ if ( init_ssl && ( 0 != slapd_ssl_init())) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: SSL Initialization Failed.\n", 0, 0, 0 );
+ exit( 1 );
+ }
+
+ /*
+ * if we were called upon to do special database stuff, do it and be
+ * done.
+ */
+ switch ( slapd_exemode ) {
+ case SLAPD_EXEMODE_LDIF2DB:
+ return slapd_exemode_ldif2db();
+
+ case SLAPD_EXEMODE_DB2LDIF:
+ return slapd_exemode_db2ldif(argc,argv);
+
+ case SLAPD_EXEMODE_DB2INDEX:
+ return slapd_exemode_db2index();
+
+ case SLAPD_EXEMODE_ARCHIVE2DB:
+ return slapd_exemode_archive2db();
+
+ case SLAPD_EXEMODE_DB2ARCHIVE:
+ return slapd_exemode_db2archive();
+
+ case SLAPD_EXEMODE_DBTEST:
+ return slapd_exemode_dbtest();
+
+ case SLAPD_EXEMODE_REFERRAL:
+ /* check that all the necessary info was given, then go on */
+ if (! config_check_referral_mode()) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: No referral URL supplied\n", 0, 0, 0);
+ usage( myname, extraname );
+ exit(1);
+ }
+ break;
+
+ case SLAPD_EXEMODE_SUFFIX2INSTANCE:
+ return slapd_exemode_suffix2instance();
+
+#if defined(UPGRADEDB)
+ case SLAPD_EXEMODE_UPGRADEDB:
+ return slapd_exemode_upgradedb();
+#endif
+
+ case SLAPD_EXEMODE_PRINTVERSION:
+ slapd_print_version(1);
+ exit(1);
+ }
+
+#if defined( XP_WIN32 )
+ /* Register with the NT EventLog */
+ hSlapdEventSource = RegisterEventSource(NULL, pszServerName );
+ if( !hSlapdEventSource )
+ {
+ char szMessage[256];
+ sprintf( szMessage, "Directory Server %s is terminating. Failed "
+ "to set the EventLog source.", pszServerName);
+ MessageBox(GetDesktopWindow(), szMessage, " ",
+ MB_ICONEXCLAMATION | MB_OK);
+ exit( 1 );
+ }
+
+ /* Check to ensure there isn't a copy of this server already running. */
+ if( MultipleInstances() )
+ exit( 1 );
+#endif
+
+ /*
+ * Detach ourselves from the terminal (unless running in debug mode).
+ * We must detach before we start any threads since detach forks() on
+ * UNIX.
+ */
+ detach();
+
+ /*
+ * Now write our PID to the startup PID file.
+ * This is used by the start up script to determine our PID quickly
+ * after we fork, without needing to wait for the 'real' pid file to be
+ * written. That could take minutes. And the start script will wait
+ * that long looking for it. With this new 'early pid' file, it can avoid
+ * doing that, by detecting the pid and watching for the process exiting.
+ * This removes the blank stares all round from start-slapd when the server
+ * fails to start for some reason
+ */
+ write_start_pid_file();
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ((slapd_exemode != SLAPD_EXEMODE_REFERRAL) &&
+ ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 )) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+
+
+ /*
+ * Now it is safe to log our first startup message. If we were to
+ * log anything earlier than now it would appear on the admin startup
+ * screen twice because before we detach everything is sent to both
+ * stderr and our error log. Yuck.
+ */
+ if (1) {
+ char *versionstring = config_get_versionstring();
+ char *buildnum = config_get_buildnum();
+ LDAPDebug( LDAP_DEBUG_ANY, "%s B%s starting up\n",
+ versionstring, buildnum, 0 );
+ slapi_ch_free((void **)&buildnum);
+ slapi_ch_free((void **)&versionstring);
+ }
+
+ /*
+ * After we read the config file we should make
+ * sure that everything we needed to read in has
+ * been read in and we'll start whatever threads,
+ * etc the backends need to start
+ */
+
+
+ /* Important: up 'till here we could be running as root (on unix).
+ * we believe that we've not created any files before here, otherwise
+ * they'd be owned by root, which is bad. We're about to change identity
+ * to some non-root user, but before we do, we call the daemon code
+ * to let it open the listen sockets. If these sockets are low-numbered,
+ * we need to be root in order to open them.
+ */
+
+ {
+ arg.n_port = (unsigned short)n_port;
+ if ( slapd_listenhost2addr( config_get_listenhost(),
+ &arg.n_listenaddr ) != 0 ) {
+ return(1);
+ }
+
+ arg.s_port = (unsigned short)s_port;
+ if ( slapd_listenhost2addr( config_get_securelistenhost(),
+ &arg.s_listenaddr ) != 0 ) {
+ return(1);
+ }
+
+ return_value = daemon_pre_setuid_init(&arg);
+ if (0 != return_value) {
+ LDAPDebug( LDAP_DEBUG_ANY, "Failed to init daemon\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ }
+
+ /* Now, sockets are open, so we can safely change identity now */
+
+#ifndef _WIN32
+ return_value = main_setuid(slapdFrontendConfig->localuser);
+ if (0 != return_value) {
+ LDAPDebug( LDAP_DEBUG_ANY, "Failed to change user and group identity to that of %s\n",
+ slapdFrontendConfig->localuser, 0, 0 );
+ exit(1);
+ }
+#endif
+
+
+ /* -sduloutre: compute_init() and entry_computed_attr_init() moved up */
+
+ if (slapd_exemode != SLAPD_EXEMODE_REFERRAL) {
+ int rc;
+ Slapi_DN *sdn;
+
+ fedse_create_startOK(DSE_FILENAME, DSE_STARTOKFILE,
+ slapdFrontendConfig->configdir);
+
+ eq_init(); /* must be done before plugins started */
+ snmp_collator_start();
+ ps_init_psearch_system(); /* must come before plugin_startall() */
+
+ /* Initailize the mapping tree */
+
+ if (mapping_tree_init())
+ {
+ LDAPDebug( LDAP_DEBUG_ANY, "Failed to init mapping tree\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+
+
+ /* initialize UniqueID generator - must be done once backends are started
+ and event queue is initialized but before plugins are started */
+ sdn = slapi_sdn_new_dn_byval ("cn=uniqueid generator,cn=config");
+ rc = uniqueIDGenInit (NULL, sdn, slapd_exemode == SLAPD_EXEMODE_SLAPD);
+ slapi_sdn_free (&sdn);
+ if (rc != UID_SUCCESS)
+ {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Fatal Error---Failed to initialize uniqueid generator; error = %d. "
+ "Exiting now.\n", rc, 0, 0 );
+ exit( 1 );
+ }
+
+ /* --ugaston: register the start-tls plugin */
+#ifndef _WIN32
+ if ( slapd_security_library_is_initialized() != 0 ) {
+ start_tls_register_plugin();
+ LDAPDebug( LDAP_DEBUG_PLUGIN,
+ "Start TLS plugin registered.\n",
+ 0, 0, 0 );
+ }
+#endif
+
+ plugin_startall(argc, argv, 1 /* Start Backends */, 1 /* Start Globals */);
+ if (housekeeping_start((time_t)0, NULL) == NULL) {
+ exit (1);
+ }
+
+ eq_start(); /* must be done after plugins started */
+
+#ifdef HPUX10
+ /* HPUX linker voodoo */
+ if (collation_init == NULL) {
+ exit (1);
+ }
+
+#endif /* HPUX */
+
+ normalize_oc();
+
+ if (n_port) {
+#if defined(NET_SSL)
+ } else if ( config_get_security()) {
+#endif
+ } else {
+#ifdef _WIN32
+ if( SlapdIsAService() )
+ {
+ LDAPServerStatus.dwCurrentState = SERVICE_STOPPED;
+ LDAPServerStatus.dwCheckPoint = 0;
+ LDAPServerStatus.dwWaitHint = 0;
+ LDAPServerStatus.dwWin32ExitCode = 1;
+ LDAPServerStatus.dwServiceSpecificExitCode = 1;
+
+ SetServiceStatus(hLDAPServerServiceStatus, &LDAPServerStatus);
+
+ /* Log this event */
+ ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_START_FAILED, 1,
+ "Check server port specification");
+ }
+ else
+ {
+ char szMessage[256];
+ sprintf( szMessage, "The Directory Server %s is terminating due to an error. Check server port specification", pszServerName);
+ MessageBox(GetDesktopWindow(), szMessage, " ", MB_ICONEXCLAMATION | MB_OK);
+ }
+#endif
+ exit(1);
+ }
+ }
+
+ {
+ Slapi_PBlock pb;
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = be;
+ }
+
+ if (slapd_exemode != SLAPD_EXEMODE_REFERRAL) {
+ /* else do this after seteuid() */
+ lite_entries_init();
+
+ /* setup cn=tasks tree */
+ task_init();
+
+ /* pw_init() needs to be here since it uses aci function calls. */
+ pw_init();
+ /* Initialize the sasl mapping code */
+ if (sasl_map_init()) {
+ LDAPDebug( LDAP_DEBUG_ANY, "Failed to initialize sasl mapping code\n", 0, 0, 0 );
+ }
+ }
+
+ /*
+ * search_register_reslimits() and daemon_register_reslimits() can
+ * be called any time before we start accepting client connections.
+ * We call these even when running in referral mode because they
+ * do little harm and registering at least one resource limit forces
+ * the reslimit subsystem to initialize itself... which prevents
+ * strange error messages from being logged to the error log for
+ * the first LDAP connection.
+ */
+ if ( search_register_reslimits() != SLAPI_RESLIMIT_STATUS_SUCCESS ||
+ daemon_register_reslimits() != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
+ exit( 1 );
+ }
+
+ {
+ time( &starttime );
+
+ slapd_daemon(&arg);
+ }
+ LDAPDebug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
+ reslimit_cleanup();
+ compute_terminate();
+ vattr_cleanup();
+ sasl_map_done();
+ PR_Cleanup();
+#ifdef _WIN32
+ /* Clean up the mutex used to interlock processes, before we exit */
+ remove_slapd_process();
+#endif
+#if ( defined( hpux ) || defined( irix ) || defined( aix ) || defined( OSF1 ))
+ exit( 0 );
+#else
+ return 0;
+#endif
+}
+
+
+#if ( defined( hpux ) || defined( irix ))
+void *
+signal2sigaction( int s, void *a )
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_handler = (VFP)a;
+ act.sa_flags = 0;
+ (void)sigemptyset( &act.sa_mask );
+ (void)sigaddset( &act.sa_mask, s );
+ (void)sigaction( s, &act, NULL );
+}
+#endif /* hpux || irix */
+
+static void
+register_objects()
+{
+ get_operation_object_type();
+ daemon_register_connection();
+ get_entry_object_type();
+ mapping_tree_get_extension_type ();
+}
+
+static void
+process_command_line(int argc, char **argv, char *myname,
+ char **extraname)
+{
+ int i;
+ char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
+ char *opts;
+ static struct opt_ext *long_opts;
+ int longopt_index=0;
+
+ /*
+ * Refer to the file getopt_ext.h for an overview of how to use the
+ * long option names
+ *
+ */
+
+
+ /*
+ * when a new option letter is used, please move it from the "available"
+ * list to the "used" list.
+ *
+ */
+ /*
+ * single-letter options already in use:
+ *
+ * a C c D E d f G g i
+ * L l N m n O o P p r S s T t
+ * u v V w x Z z
+ *
+ * 1
+ *
+ */
+
+ /*
+ * single-letter options still available:
+ *
+ * A B b e F H h I J j
+ * K k M Q q R
+ * W X Y y
+ *
+ * 2 3 4 5 6 7 8 9 0
+ *
+ */
+
+ char *opts_dbtest = "vd:n:SD:";
+ struct opt_ext long_options_dbtest[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"backend",ArgRequired,'n'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+
+
+ char *opts_db2ldif = "vd:D:ENa:rs:x:CSut:n:UmMo1";
+ struct opt_ext long_options_db2ldif[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"dontPrintKey",ArgNone,'n'},
+ {"archive",ArgRequired,'a'},
+ {"replica",ArgNone,'r'},
+ {"include",ArgRequired,'s'},
+ {"exclude",ArgRequired,'x'},
+ /*{"whatshouldwecallthis",ArgNone,'C'},*/
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"noUniqueIds",ArgNone,'u'},
+ {"instanceDir",ArgRequired,'D'},
+ {"encrypt",ArgOptional,'E'},
+ {"nowrap",ArgNone,'U'},
+ {"minimalEncode",ArgNone,'m'},
+ {"oneOutputFile",ArgNone,'o'},
+ {"multipleOutputFile",ArgNone,'M'},
+ {"noVersionNum",ArgNone,'1'},
+ {0,0,0}};
+
+ char *opts_ldif2db = "vd:i:g:G:n:s:x:NOCc:St:D:E";
+ struct opt_ext long_options_ldif2db[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"ldiffile",ArgRequired,'i'},
+ {"generateUniqueId",ArgOptional,'g'},
+ {"backend",ArgRequired,'n'},
+ {"include",ArgRequired,'s'},
+ {"exclude",ArgRequired,'x'},
+ {"noindex",ArgNone,'O'},
+ /*{"whatshouldwecallthis",ArgNone,'C'},*/
+ /*{"whatshouldwecallthis",ArgRequired,'c'},*/
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"namespaceid", ArgRequired, 'G'},
+ {"nostate",ArgNone,'Z'},
+ {"instanceDir",ArgRequired,'D'},
+ {"encrypt",ArgOptional,'E'},
+ {0,0,0}};
+
+ char *opts_archive2db = "vd:i:a:SD:";
+ struct opt_ext long_options_archive2db[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"pidfile",ArgRequired,'i'},
+ {"archive",ArgRequired,'a'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+
+
+ char *opts_db2archive = "vd:i:a:SD:";
+ struct opt_ext long_options_db2archive[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"pidfile",ArgRequired,'i'},
+ {"archive",ArgRequired,'a'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+
+ char *opts_db2index = "vd:a:t:T:SD:n:s:x:";
+ struct opt_ext long_options_db2index[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"backend",ArgRequired,'n'},
+ {"archive",ArgRequired,'a'},
+ {"indexAttribute",ArgRequired,'t'},
+ {"vlvIndex",ArgRequired,'T'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {"include",ArgRequired,'s'},
+ {"exclude",ArgRequired,'x'},
+ {0,0,0}};
+
+#if defined(UPGRADEDB)
+ char *opts_upgradedb = "vfd:a:D:";
+ struct opt_ext long_options_upgradedb[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"force",ArgNone,'f'},
+ {"archive",ArgRequired,'a'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+#endif
+
+ char *opts_referral = "vd:p:r:SD:";
+ struct opt_ext long_options_referral[] = {
+ {"version",ArgNone,'v'},
+ {"debug",ArgRequired,'d'},
+ {"port",ArgRequired,'p'},
+ {"referralMode",ArgRequired,'r'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+
+ char *opts_suffix2instance = "s:D:";
+ struct opt_ext long_options_suffix2instance[] = {
+ {"suffix",ArgRequired,'s'},
+ {"instanceDir",ArgRequired,'D'},
+ {0,0,0}};
+
+ char *opts_slapd = "vVd:i:SD:w:";
+ struct opt_ext long_options_slapd[] = {
+ {"version",ArgNone,'v'},
+ {"versionFull",ArgNone,'V'},
+ {"debug",ArgRequired,'d'},
+ {"pidfile",ArgRequired,'i'},
+ {"allowMultipleProcesses",ArgNone,'S'},
+ {"instanceDir",ArgRequired,'D'},
+ {"startpidfile",ArgRequired,'w'},
+ {0,0,0}};
+
+ /*
+ * determine which of serveral modes we are executing in.
+ */
+ *extraname = NULL;
+ if (( slapd_exemode = name2exemode( myname, myname, 0 ))
+ == SLAPD_EXEMODE_UNKNOWN ) {
+
+
+ if ( argv[1] != NULL && argv[1][0] != '-' ) {
+ slapd_exemode = name2exemode( myname, argv[1], 1 );
+ *extraname = argv[1];
+ optind_ext = 2; /* make getopt() skip argv[1] */
+ optind = 2;
+ }
+ }
+ if ( slapd_exemode == SLAPD_EXEMODE_UNKNOWN ) {
+ slapd_exemode = SLAPD_EXEMODE_SLAPD; /* default */
+ }
+ /*
+ * richm: If running in regular slapd server mode, allow the front
+ * end dse files (dse.ldif and ldbm.ldif) to be written in case of
+ * additions or modifications. In all other modes, these files
+ * should only be read and never written.
+ */
+
+ if (slapd_exemode == SLAPD_EXEMODE_SLAPD ||
+ slapd_exemode == SLAPD_EXEMODE_ARCHIVE2DB || /* bak2db adjusts config */
+ slapd_exemode == SLAPD_EXEMODE_UPGRADEDB) /* update idl-switch */
+ dse_unset_dont_ever_write_dse_files();
+
+ /* maintain compatibility with pre-5.x options */
+ switch( slapd_exemode ) {
+ case SLAPD_EXEMODE_DBTEST:
+ opts = opts_dbtest;
+ long_opts = long_options_dbtest;
+ break;
+ case SLAPD_EXEMODE_DB2LDIF:
+ opts = opts_db2ldif;
+ long_opts = long_options_db2ldif;
+ break;
+ case SLAPD_EXEMODE_LDIF2DB:
+ opts = opts_ldif2db;
+ long_opts = long_options_ldif2db;
+ break;
+ case SLAPD_EXEMODE_ARCHIVE2DB:
+ opts = opts_archive2db;
+ long_opts = long_options_archive2db;
+ break;
+ case SLAPD_EXEMODE_DB2ARCHIVE:
+ init_cmd_shutdown_detect();
+ opts = opts_db2archive;
+ long_opts = long_options_db2archive;
+ break;
+ case SLAPD_EXEMODE_DB2INDEX:
+ opts = opts_db2index;
+ long_opts = long_options_db2index;
+ break;
+ case SLAPD_EXEMODE_REFERRAL:
+ opts = opts_referral;
+ long_opts = long_options_referral;
+ break;
+ case SLAPD_EXEMODE_SUFFIX2INSTANCE:
+ opts = opts_suffix2instance;
+ long_opts = long_options_suffix2instance;
+ break;
+#if defined(UPGRADEDB)
+ case SLAPD_EXEMODE_UPGRADEDB:
+ opts = opts_upgradedb;
+ long_opts = long_options_upgradedb;
+ break;
+#endif
+ default: /* SLAPD_EXEMODE_SLAPD */
+ opts = opts_slapd;
+ long_opts = long_options_slapd;
+ }
+
+ while ( (i = getopt_ext( argc, argv, opts,
+ long_opts, &longopt_index)) != EOF ) {
+ char *instancedir = 0;
+ switch ( i ) {
+#ifdef LDAP_DEBUG
+ case 'd': /* turn on debugging */
+ if ( optarg_ext[0] == '?'
+ || 0 == strcasecmp( optarg_ext, "help" )) {
+ slapd_debug_level_usage();
+ exit( 1 );
+ } else {
+ should_detach = 0;
+ slapd_ldap_debug = slapd_debug_level_string2level( optarg_ext );
+ if ( slapd_ldap_debug < 0 ) {
+ slapd_debug_level_usage();
+ exit( 1 );
+ }
+ slapd_ldap_debug |= LDAP_DEBUG_ANY;
+ }
+ break;
+#else
+ case 'd': /* turn on debugging */
+ fprintf( stderr,
+ "must compile with LDAP_DEBUG for debugging\n" );
+ break;
+#endif
+
+ case 'D': /* config dir */
+ instancedir = rel2abspath( optarg_ext );
+
+#if defined( XP_WIN32 )
+ pszServerName = slapi_ch_malloc( MAX_SERVICE_NAME );
+ if( !SlapdGetServerNameFromCmdline(pszServerName, instancedir, 1) )
+ {
+ MessageBox(GetDesktopWindow(), "Failed to get the Directory"
+ " Server name from the command-line argument.",
+ " ", MB_ICONEXCLAMATION | MB_OK);
+ exit( 1 );
+ }
+#endif
+ if ( config_set_instancedir( "instancedir (-D)",
+ instancedir, errorbuf, 1) != LDAP_SUCCESS ) {
+ fprintf( stderr, "%s: aborting now\n", errorbuf );
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ slapi_ch_free((void **)&instancedir);
+
+ break;
+
+ case 'p': /* port on which to listen (referral mode only) */
+ if ( config_set_port ( "portnumber (-p)", optarg_ext,
+ errorbuf, CONFIG_APPLY ) != LDAP_SUCCESS ) {
+ fprintf( stderr, "%s: aborting now\n", errorbuf );
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ break;
+
+ case 'i': /* set pid log file or ldif2db LDIF file */
+ if ( slapd_exemode == SLAPD_EXEMODE_LDIF2DB ) {
+ char *p;
+ /* if LDIF comes through standard input, skip path checking */
+ if ( optarg_ext[0] != '-' || strlen(optarg_ext) != 1) {
+#if defined( XP_WIN32 )
+ if ( optarg_ext[0] != '/' && optarg_ext[0] != '\\'
+ && (!isalpha( optarg_ext[0] ) || (optarg_ext[1] != ':')) ) {
+ fprintf( stderr, "%s file could not be opened: absolute path "
+ " required.\n", optarg_ext );
+ break;
+ }
+#else
+ if ( optarg_ext[ 0 ] != '/' ) {
+ fprintf( stderr, "%s file could not be opened: absolute path "
+ " required.\n", optarg_ext );
+ break;
+ }
+#endif
+ }
+ p = (char *) slapi_ch_malloc(strlen(optarg_ext) + 1);
+
+ strcpy(p, optarg_ext);
+ charray_add(&ldif_file, p);
+ ldif_files++;
+ } else {
+ pid_file = rel2abspath( optarg_ext );
+ }
+ break;
+ case 'w': /* set startup pid file */
+ start_pid_file = rel2abspath( optarg_ext );
+ break;
+ case 'n': /* which backend to do ldif2db for */
+ if (slapd_exemode == SLAPD_EXEMODE_LDIF2DB ||
+ slapd_exemode == SLAPD_EXEMODE_DBTEST ||
+ slapd_exemode == SLAPD_EXEMODE_DB2INDEX) {
+ /* The -n argument will give the name of a backend instance. */
+ cmd_line_instance_name = optarg_ext;
+ } else if (slapd_exemode == SLAPD_EXEMODE_DB2LDIF) {
+ char *s = slapi_ch_strdup(optarg_ext);
+ charray_add(&cmd_line_instance_names, s);
+ } else {
+ ldif_backend = atoi( optarg_ext );
+ }
+ break;
+ case 's': /* which suffix to include in import/export */
+ {
+ char *s= slapi_dn_normalize ( slapi_ch_strdup(optarg_ext) );
+ charray_add(&db2ldif_include,s);
+ }
+ break;
+ case 'x': /* which suffix to exclude in import/export */
+ {
+ char *s= slapi_dn_normalize ( slapi_ch_strdup(optarg_ext) );
+ charray_add(&db2ldif_exclude,s);
+ }
+ break;
+ case 'r': /* db2ldif for replication */
+ if (slapd_exemode == SLAPD_EXEMODE_REFERRAL) {
+ if (config_set_referral_mode( "referral (-r)", optarg_ext,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS) {
+ fprintf(stderr, "%s: aborting now\n",
+ errorbuf);
+ usage(myname, *extraname);
+ exit(1);
+ }
+ break;
+ }
+ if (slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ db2ldif_dump_replica = 1;
+ break;
+ case 'N': /* do not do ldif2db duplicate value check */
+ if ( slapd_exemode != SLAPD_EXEMODE_LDIF2DB &&
+ slapd_exemode != SLAPD_EXEMODE_DB2LDIF) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ /*
+ * -N flag is obsolete, but we silently accept it
+ * so we don't break customer's scripts.
+ */
+
+ /* The -N flag now does what the -n flag used to do for db2ldif.
+ * This is so -n cane be used for the instance name just like
+ * with ldif2db. */
+ if ( slapd_exemode == SLAPD_EXEMODE_DB2LDIF ) {
+ ldif_printkey &= ~EXPORT_PRINTKEY;
+ }
+
+ break;
+
+ case 'U': /* db2ldif only */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ /*
+ * don't fold (wrap) long lines (default is to fold),
+ * as of ldapsearch -T
+ */
+ ldif_printkey |= EXPORT_NOWRAP;
+
+ break;
+
+ case 'm': /* db2ldif only */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ /* minimal base64 encoding */
+ ldif_printkey |= EXPORT_MINIMAL_ENCODING;
+
+ break;
+
+ case 'M': /* db2ldif only */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ /*
+ * output ldif is stored in several file called intance_filename.
+ * by default, all instances are stored in the single filename.
+ */
+ ldif_printkey &= ~EXPORT_APPENDMODE;
+
+ break;
+
+ case 'o': /* db2ldif only */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ /*
+ * output ldif is stored in one file.
+ * by default, each instance is stored in instance_filename.
+ */
+ ldif_printkey |= EXPORT_APPENDMODE;
+
+ break;
+
+ case 'C':
+ if (slapd_exemode == SLAPD_EXEMODE_LDIF2DB) {
+ /* used to mean "Cool new import" (which is now
+ * the default) -- ignore
+ */
+ break;
+ }
+ if (slapd_exemode == SLAPD_EXEMODE_DB2LDIF) {
+ /* possibly corrupted db -- don't look at any
+ * file except id2entry. yet another overloaded
+ * flag.
+ */
+ ldif_printkey |= EXPORT_ID2ENTRY_ONLY;
+ break;
+ }
+ usage( myname, *extraname );
+ exit( 1 );
+
+ case 'c': /* merge chunk size for Cool new import */
+ if ( slapd_exemode != SLAPD_EXEMODE_LDIF2DB ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ ldif2db_removedupvals = atoi(optarg_ext); /* We overload this flag---ok since we always check for dupes in the new code */
+ break;
+
+ case 'O': /* only create core db, no attr indexes */
+ if ( slapd_exemode != SLAPD_EXEMODE_LDIF2DB ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ ldif2db_noattrindexes = 1;
+ break;
+
+ case 't': /* attribute type to index - may be repeated */
+ case 'T': /* VLV Search to index - may be repeated */
+ if ( slapd_exemode == SLAPD_EXEMODE_DB2INDEX ) {
+ char *p= slapi_ch_malloc(strlen(optarg_ext) + 2);
+ sprintf(p,"%c%s",i,optarg_ext);
+ charray_add( &db2index_attrs, p);
+ break;
+ }
+ usage( myname, *extraname );
+ exit(1);
+
+ case 'v': /* print version and exit */
+ slapd_print_version(0);
+ exit( 1 );
+ break;
+
+ case 'V':
+ slapd_exemode = SLAPD_EXEMODE_PRINTVERSION;
+ break;
+
+ case 'a': /* archive pathname for db */
+ archive_name = optarg_ext;
+ break;
+
+ case 'Z':
+ if (slapd_exemode == SLAPD_EXEMODE_LDIF2DB)
+ {
+ ldif2db_load_state= 0;
+ break;
+ }
+ usage( myname, *extraname );
+ exit(1);
+ case 'S': /* skip the check for slad running in conflicting modes */
+ skip_db_protect_check = 1;
+ break;
+ case 'u': /* do not dump uniqueid for db2ldif */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ db2ldif_dump_uniqueid = 0;
+ break;
+ case 'g': /* generate uniqueid for ldif2db */
+ if ( slapd_exemode != SLAPD_EXEMODE_LDIF2DB ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ if (optarg_ext == NULL){
+ printf ("ldif2db: generation type is not specified for -g; "
+ "random generation is used\n");
+ ldif2db_generate_uniqueid = SLAPI_UNIQUEID_GENERATE_TIME_BASED;
+ }
+ else if (strcasecmp (optarg_ext, "none") == 0)
+ ldif2db_generate_uniqueid = SLAPI_UNIQUEID_GENERATE_NONE;
+ else if (strcasecmp (optarg_ext, "deterministic") == 0) /* name based */
+ ldif2db_generate_uniqueid = SLAPI_UNIQUEID_GENERATE_NAME_BASED;
+ else /* default - time based */
+ ldif2db_generate_uniqueid = SLAPI_UNIQUEID_GENERATE_TIME_BASED;
+ break;
+ case 'G': /* namespace id for name based uniqueid generation for ldif2db */
+ if ( slapd_exemode != SLAPD_EXEMODE_LDIF2DB ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ ldif2db_namespaceid = optarg_ext;
+ break;
+ case 'E': /* encrypt data if importing, decrypt if exporting */
+ if ( (slapd_exemode != SLAPD_EXEMODE_LDIF2DB) && (slapd_exemode != SLAPD_EXEMODE_DB2LDIF)) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ importexport_encrypt = 1;
+ break;
+#if defined(UPGRADEDB)
+ case 'f': /* upgradedb only */
+ if ( slapd_exemode != SLAPD_EXEMODE_UPGRADEDB ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ upgradedb_force = SLAPI_UPGRADEDB_FORCE;
+ break;
+#endif
+ case '1': /* db2ldif only */
+ if ( slapd_exemode != SLAPD_EXEMODE_DB2LDIF ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ /*
+ * do not output "version: 1" to the ldif file
+ */
+ ldif_printkey |= EXPORT_NOVERSION;
+
+ break;
+ default:
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+ }
+
+ if ((NULL != cmd_line_instance_names)
+ && (NULL != cmd_line_instance_names[1])
+ && (ldif_printkey & EXPORT_APPENDMODE))
+ {
+ fprintf(stderr, "WARNING: several backends are being"
+ " exported to a single ldif file\n");
+ fprintf(stderr, " use option -M to export to"
+ " multiple ldif files\n");
+ }
+ /* Any leftover arguments? */
+ if ( optind_last > optind ) {
+ usage( myname, *extraname );
+ exit( 1 );
+ }
+
+ return;
+}
+
+static int
+lookup_instance_name_by_suffix(char *suffix,
+ char ***suffixes, char ***instances, int isexact)
+{
+ Slapi_PBlock *pb = slapi_pblock_new();
+ Slapi_Entry **entries = NULL, **ep;
+ char *query;
+ char *backend;
+ char *fullsuffix;
+ int rval = -1;
+
+ if (pb == NULL)
+ goto done;
+
+ query = slapi_ch_malloc(strlen((const char *)suffix) + 80); /* round up */
+
+ if (query == NULL)
+ goto done;
+
+ if (isexact)
+ sprintf(query, "(&(objectclass=nsmappingtree)(|(cn=\"%s\")(cn=%s)))", suffix, suffix);
+ else
+ sprintf(query, "(&(objectclass=nsmappingtree)(|(cn=*%s\")(cn=*%s)))", suffix, suffix);
+
+ slapi_search_internal_set_pb(pb, "cn=mapping tree,cn=config",
+ LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
+ (void *)plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_ch_free((void **)&query);
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
+ if (rval != LDAP_SUCCESS)
+ goto done;
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if ((entries == NULL) || (entries[0] == NULL))
+ goto done;
+
+ rval = 0;
+ for (ep = entries; *ep; ep++) {
+ backend = slapi_entry_attr_get_charptr(*ep, "nsslapd-backend");
+ if (backend) {
+ charray_add(instances, backend);
+ if (suffixes) {
+ fullsuffix = slapi_entry_attr_get_charptr(*ep, "cn");
+ charray_add(suffixes, fullsuffix); /* NULL is ok */
+ }
+ }
+ }
+
+done:
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ return rval;
+}
+
+int
+lookup_instance_name_by_suffixes(char **included, char **excluded,
+ char ***instances)
+{
+ char **incl_instances, **excl_instances;
+ char **p;
+ int rval = -1;
+
+ incl_instances = NULL;
+ for (p = included; p && *p; p++) {
+ if (lookup_instance_name_by_suffix(*p, NULL, &incl_instances, 0) < 0)
+ return rval;
+ }
+
+ excl_instances = NULL;
+ for (p = excluded; p && *p; p++) {
+ if (lookup_instance_name_by_suffix(*p, NULL, &excl_instances, 0) < 0)
+ return rval;
+ }
+
+ rval = 0;
+ charray_subtract(incl_instances, excl_instances, NULL);
+ charray_free(excl_instances);
+ *instances = incl_instances;
+ return rval;
+}
+
+/* helper function for ldif2db & friends -- given an instance name, lookup
+ * the plugin name in the DSE. this assumes the DSE has already been loaded.
+ */
+static struct slapdplugin *lookup_plugin_by_instance_name(const char *name)
+{
+ Slapi_Entry **entries = NULL;
+ Slapi_PBlock *pb = slapi_pblock_new();
+ struct slapdplugin *plugin;
+ char *query, *dn, *cn;
+ int ret = 0;
+
+ if (pb == NULL)
+ return NULL;
+
+ query = slapi_ch_malloc(strlen(name) + 80); /* round up */
+ if (query == NULL) {
+ slapi_pblock_destroy(pb);
+ return NULL;
+ }
+ sprintf(query, "(&(cn=%s)(objectclass=nsBackendInstance))", name);
+
+ slapi_search_internal_set_pb(pb, "cn=plugins,cn=config",
+ LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
+ (void *)plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_ch_free((void **)&query);
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
+ if (ret != LDAP_SUCCESS) {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ return NULL;
+ }
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if ((entries == NULL) || (entries[0] == NULL)) {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ return NULL;
+ }
+
+ /* okay -- have the entry for this instance, now let's chop up the dn */
+ /* parent dn is the plugin */
+ dn = slapi_dn_parent(slapi_entry_get_dn(entries[0]));
+
+ /* clean up */
+ slapi_free_search_results_internal(pb);
+ entries = NULL;
+ slapi_pblock_destroy(pb);
+ pb = NULL; /* this seems redundant . . . until we add code after this line */
+
+ /* now... look up the parent */
+ pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_BASE,
+ "(objectclass=nsSlapdPlugin)", NULL, 0, NULL, NULL,
+ (void *)plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_ch_free((void **)&dn);
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
+ if (ret != LDAP_SUCCESS) {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ return NULL;
+ }
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if ((entries == NULL) || (entries[0] == NULL)) {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ return NULL;
+ }
+
+ cn = slapi_entry_attr_get_charptr(entries[0], "cn");
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+
+ plugin = plugin_get_by_name(cn);
+ slapi_ch_free((void **)&cn);
+
+ return plugin;
+}
+
+static int
+slapd_exemode_ldif2db()
+{
+ int return_value= 0;
+ Slapi_PBlock pb;
+ struct slapdplugin *plugin;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ( ldif_file == NULL ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: Required argument -i <ldiffile> missing\n",
+ 0, 0, 0 );
+ usage( myname, extraname );
+ exit( 1 );
+ }
+
+ /* this should be the first time this are called! if the init order
+ * is ever changed, these lines should be changed (or erased)!
+ */
+ mapping_tree_init();
+
+ /*
+ * if instance is given, just use it to get the backend.
+ * otherwise, we use included/excluded suffix list to specify a backend.
+ */
+ if (NULL == cmd_line_instance_name) {
+ char **instances, **ip;
+ int counter;
+
+ if (lookup_instance_name_by_suffixes(db2ldif_include, db2ldif_exclude,
+ &instances) < 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: backend instances name [-n <name>] or "
+ "included suffix [-s <suffix>] need to be specified.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+
+ if (instances) {
+ for (ip = instances, counter = 0; ip && *ip; ip++, counter++)
+ ;
+
+ if (counter == 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 1: There is no backend instance to import to.\n",
+ 0, 0, 0);
+ exit(1);
+ } else if (counter > 1) {
+ int i;
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: There are multiple backend instances specified:\n",
+ 0, 0, 0);
+ for (i = 0; i < counter; i++)
+ LDAPDebug(LDAP_DEBUG_ANY, " : %s\n",
+ instances[i], 0, 0);
+ exit(1);
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend Instance: %s\n",
+ *instances, 0, 0);
+ cmd_line_instance_name = *instances;
+ }
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 2: There is no backend instance to import to.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ }
+
+ plugin = lookup_plugin_by_instance_name(cmd_line_instance_name);
+ if (plugin == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find backend '%s'.\n",
+ cmd_line_instance_name, 0, 0);
+ exit(1);
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 ) {
+
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ /* check for slapi v2 support */
+ if (! SLAPI_PLUGIN_IS_V2(plugin)) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ERROR: %s is too old to do imports.\n",
+ plugin->plg_name, 0, 0);
+ exit(1);
+ }
+
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = plugin;
+ pb.pb_removedupvals = ldif2db_removedupvals;
+ pb.pb_ldif2db_noattrindexes = ldif2db_noattrindexes;
+ pb.pb_ldif_generate_uniqueid = ldif2db_generate_uniqueid;
+ pb.pb_ldif_namespaceid = ldif2db_namespaceid;
+ pb.pb_ldif_encrypt = importexport_encrypt;
+/* pb.pb_ldif_load_state = ldif2db_load_state; */
+ pb.pb_instance_name = cmd_line_instance_name;
+ pb.pb_ldif_files = ldif_file;
+ pb.pb_ldif_include = db2ldif_include;
+ pb.pb_ldif_exclude = db2ldif_exclude;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+#ifndef _WIN32
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ if ( plugin->plg_ldif2db != NULL ) {
+ return_value = (*plugin->plg_ldif2db)( &pb );
+ } else {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: no ldif2db function defined for "
+ "%s\n", plugin->plg_name, 0, 0 );
+ return_value = -1;
+ }
+ slapi_ch_free((void**)&myname );
+ charray_free( db2index_attrs );
+ charray_free(ldif_file);
+ return( return_value );
+}
+
+static int
+slapd_exemode_db2ldif(int argc, char** argv)
+{
+ int return_value= 0;
+ Slapi_PBlock pb;
+ struct slapdplugin *plugin;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ char *my_ldiffile;
+ char **instp;
+
+ /* this should be the first time this are called! if the init order
+ * is ever changed, these lines should be changed (or erased)!
+ */
+ mapping_tree_init();
+
+ /*
+ * if instance is given, just pass it to the backend.
+ * otherwise, we use included/excluded suffix list to specify a backend.
+ */
+ if (NULL == cmd_line_instance_names) {
+ char **instances, **ip;
+ int counter;
+
+ if (lookup_instance_name_by_suffixes(db2ldif_include, db2ldif_exclude,
+ &instances) < 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: backend instances name [-n <name>] or "
+ "included suffix [-s <suffix>] need to be specified.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+
+ if (instances) {
+ for (ip = instances, counter = 0; ip && *ip; ip++, counter++)
+ ;
+
+ if (counter == 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 1: There is no backend instance to export from.\n",
+ 0, 0, 0);
+ exit(1);
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend Instance: %s\n",
+ *instances, 0, 0);
+ cmd_line_instance_names = instances;
+ }
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 2: There is no backend instance to export from.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ }
+
+#ifndef _WIN32
+ /* [622984] db2lidf -r changes database file ownership
+ * should call setuid before "db2ldif_dump_replica" */
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ for (instp = cmd_line_instance_names; instp && *instp; instp++) {
+ int release_me = 0;
+
+ plugin = lookup_plugin_by_instance_name(*instp);
+ if (plugin == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find backend '%s'.\n",
+ *instp, 0, 0);
+ exit(1);
+ }
+
+ if (plugin->plg_db2ldif == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ERROR: no db2ldif function defined for "
+ "backend %s - cannot export\n", *instp, 0, 0);
+ exit(1);
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts "
+ "with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ if ( config_is_slapd_lite () &&
+ !slapi_config_get_readonly () && is_slapd_running() ) {
+ LDAPDebug( LDAP_DEBUG_ANY, "%s\n", LITE_BACKUP_ERR, 0, 0);
+ exit ( 1 );
+ }
+
+ if (! (SLAPI_PLUGIN_IS_V2(plugin))) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ERROR: %s is too old to do exports.\n",
+ plugin->plg_name, 0, 0);
+ exit(1);
+ }
+
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = plugin;
+ pb.pb_ldif_include = db2ldif_include;
+ pb.pb_ldif_exclude = db2ldif_exclude;
+ pb.pb_ldif_dump_replica = db2ldif_dump_replica;
+ pb.pb_ldif_dump_uniqueid = db2ldif_dump_uniqueid;
+ pb.pb_ldif_encrypt = importexport_encrypt;
+ pb.pb_instance_name = *instp;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+ if (is_slapd_running())
+ pb.pb_server_running = 1;
+ else
+ pb.pb_server_running = 0;
+
+ if (db2ldif_dump_replica) {
+ eq_init(); /* must be done before plugins started */
+ ps_init_psearch_system(); /* must come before plugin_startall() */
+ plugin_startall(argc, argv, 1 /* Start Backends */,
+ 1 /* Start Globals */);
+ eq_start(); /* must be done after plugins started */
+ }
+
+ pb.pb_ldif_file = NULL;
+ if ( archive_name ) { /* redirect stdout to this file: */
+ char *p, *q;
+#if defined( XP_WIN32 )
+ char sep = '\\';
+ if (NULL != strchr(archive_name, '/'))
+ sep = '/';
+#else
+ char sep = '/';
+#endif
+ my_ldiffile = archive_name;
+ if (ldif_printkey & EXPORT_APPENDMODE) {
+ if (instp == cmd_line_instance_names) { /* first export */
+ ldif_printkey |= EXPORT_APPENDMODE_1;
+ } else {
+ ldif_printkey &= ~EXPORT_APPENDMODE_1;
+ }
+ } else { /* not APPENDMODE */
+ if (strcmp(archive_name, "-")) { /* not '-' */
+ my_ldiffile =
+ (char *)slapi_ch_malloc((unsigned long)(strlen(archive_name)
+ + strlen(*instp) + 2));
+ p = strrchr(archive_name, sep);
+ if (NULL == p) {
+ sprintf(my_ldiffile, "%s_%s", *instp, archive_name);
+ } else {
+ q = p + 1;
+ *p = '\0';
+ sprintf(my_ldiffile, "%s%c%s_%s",
+ archive_name, sep, *instp, q);
+ *p = sep;
+ }
+ release_me = 1;
+ }
+ }
+
+ fprintf(stderr, "ldiffile: %s\n", my_ldiffile);
+ /* just send the filename to the backend and let
+ * the backend open it (so they can do special
+ * stuff for 64-bit fs)
+ */
+ pb.pb_ldif_file = my_ldiffile;
+ pb.pb_ldif_printkey = ldif_printkey;
+ }
+
+ return_value = (plugin->plg_db2ldif)( &pb );
+
+ if (release_me) {
+ slapi_ch_free((void **)&my_ldiffile);
+ }
+ }
+ slapi_ch_free( (void**)&myname );
+ if (db2ldif_dump_replica) {
+ plugin_closeall( 1 /* Close Backends */, 1 /* Close Globals */);
+ }
+ return( return_value );
+}
+
+static int
+slapd_exemode_suffix2instance()
+{
+ int return_value = 0;
+ char **instances = NULL;
+ char **suffixes = NULL;
+ char **p, **q, **r;
+
+ /* this should be the first time this are called! if the init order
+ * is ever changed, these lines should be changed (or erased)!
+ */
+ mapping_tree_init();
+
+ for (p = db2ldif_include; p && *p; p++) {
+ if (lookup_instance_name_by_suffix(*p, &suffixes, &instances, 0) < 0)
+ continue;
+ fprintf(stderr, "Suffix, Instance name pair(s) under \"%s\":\n", *p);
+ if (instances)
+ for (q = suffixes, r = instances; *r; q++, r++)
+ fprintf(stderr, "\tsuffix %s; instance name \"%s\"\n",
+ *q?*q:"-", *r);
+ else
+ fprintf(stderr, "\tNo instance\n");
+ charray_free(suffixes);
+ suffixes = NULL;
+ charray_free(instances);
+ instances = NULL;
+ }
+ return (return_value);
+}
+
+static int slapd_exemode_db2index()
+{
+ int return_value= 0;
+ struct slapdplugin *plugin;
+ Slapi_PBlock pb;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ mapping_tree_init();
+
+ /*
+ * if instance is given, just use it to get the backend.
+ * otherwise, we use included/excluded suffix list to specify a backend.
+ */
+ if (NULL == cmd_line_instance_name) {
+ char **instances, **ip;
+ int counter;
+
+ if (lookup_instance_name_by_suffixes(db2ldif_include, db2ldif_exclude,
+ &instances) < 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: backend instances name [-n <name>] or "
+ "included suffix [-s <suffix>] need to be specified.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+
+ if (instances) {
+ for (ip = instances, counter = 0; ip && *ip; ip++, counter++)
+ ;
+
+ if (counter == 0) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 1: There is no backend instance to import to.\n",
+ 0, 0, 0);
+ exit(1);
+ } else if (counter > 1) {
+ int i;
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: There are multiple backend instances specified:\n",
+ 0, 0, 0);
+ for (i = 0; i < counter; i++)
+ LDAPDebug(LDAP_DEBUG_ANY, " : %s\n",
+ instances[i], 0, 0);
+ exit(1);
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend Instance: %s\n",
+ *instances, 0, 0);
+ cmd_line_instance_name = *instances;
+ }
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR 2: There is no backend instance to import to.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ }
+
+ plugin = lookup_plugin_by_instance_name(cmd_line_instance_name);
+ if (plugin == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find backend '%s'.\n",
+ cmd_line_instance_name, 0, 0);
+ exit(1);
+ }
+
+ /* make sure nothing else is running */
+ if (add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other "
+ "slapd processes.\n", 0, 0, 0);
+ exit(1);
+ }
+
+ if ( db2index_attrs == NULL ) {
+ usage( myname, extraname );
+ exit( 1 );
+ }
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = plugin;
+ pb.pb_db2index_attrs = db2index_attrs;
+ pb.pb_instance_name = cmd_line_instance_name;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+#ifndef _WIN32
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ return_value = (*plugin->plg_db2index)( &pb );
+
+ slapi_ch_free( (void**)&myname );
+ return( return_value );
+}
+
+
+static int
+slapd_exemode_db2archive()
+{
+ int return_value= 0;
+ Slapi_Backend *be = NULL;
+ Slapi_PBlock pb;
+ struct slapdplugin *backend_plugin;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ((backend_plugin = plugin_get_by_name("ldbm database")) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find the ldbm backend plugin.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ if (NULL == archive_name) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: no archive directory supplied\n",
+ 0, 0, 0 );
+ exit( 1 );
+ }
+
+ if ( config_is_slapd_lite () && !slapi_config_get_readonly () && is_slapd_running ()) {
+ LDAPDebug( LDAP_DEBUG_ANY, "%s\n", LITE_BACKUP_ERR, 0, 0);
+ exit ( 1 );
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ if (compute_init()) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Initialization Failed 0 %d\n",return_value,0,0);
+ exit (1);
+ }
+
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = backend_plugin;
+ pb.pb_instance_name = cmd_line_instance_name;
+ pb.pb_seq_val = archive_name;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+#ifndef _WIN32
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ return_value = (backend_plugin->plg_db2archive)( &pb );
+ return return_value;
+}
+
+static int
+slapd_exemode_archive2db()
+{
+ int return_value= 0;
+ Slapi_Backend *be = NULL;
+ Slapi_PBlock pb;
+ struct slapdplugin *backend_plugin;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ((backend_plugin = plugin_get_by_name("ldbm database")) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find the ldbm backend plugin.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ if (NULL == archive_name) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: no archive directory supplied\n",
+ 0, 0, 0 );
+ exit( 1 );
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ if (compute_init()) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Initialization Failed 0 %d\n",return_value,0,0);
+ exit (1);
+ }
+
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = backend_plugin;
+ pb.pb_instance_name = cmd_line_instance_name;
+ pb.pb_seq_val = archive_name;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+#ifndef _WIN32
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ return_value = (backend_plugin->plg_archive2db)( &pb );
+ return return_value;
+}
+
+#if defined(UPGRADEDB)
+/*
+ * functions to convert idl from the old format to the new one
+ * (604921) Support a database uprev process any time post-install
+ */
+static int
+slapd_exemode_upgradedb()
+{
+ int return_value= 0;
+ Slapi_PBlock pb;
+ struct slapdplugin *backend_plugin;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ( archive_name == NULL ) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: Required argument -a <backup_dir> missing\n",
+ 0, 0, 0 );
+ usage( myname, extraname );
+ exit( 1 );
+ }
+
+ /* this should be the first time this are called! if the init order
+ * is ever changed, these lines should be changed (or erased)!
+ */
+ mapping_tree_init();
+
+ if ((backend_plugin = plugin_get_by_name("ldbm database")) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find the ldbm backend plugin.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if (add_new_slapd_process(slapd_exemode, 0, skip_db_protect_check) == -1) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+ /* check for slapi v2 support */
+ if (! SLAPI_PLUGIN_IS_V2(backend_plugin)) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ERROR: %s is too old to do convert idl.\n",
+ backend_plugin->plg_name, 0, 0);
+ exit(1);
+ }
+
+ memset( &pb, '\0', sizeof(pb) );
+ pb.pb_backend = NULL;
+ pb.pb_plugin = backend_plugin;
+ pb.pb_seq_val = archive_name;
+ pb.pb_seq_type = upgradedb_force;
+ pb.pb_task_flags = TASK_RUNNING_FROM_COMMANDLINE;
+ /* borrowing import code, so need to set up the import variables */
+ pb.pb_ldif_generate_uniqueid = ldif2db_generate_uniqueid;
+ pb.pb_ldif_namespaceid = ldif2db_namespaceid;
+ pb.pb_ldif2db_noattrindexes = 0;
+ pb.pb_removedupvals = 0;
+#ifndef _WIN32
+ main_setuid(slapdFrontendConfig->localuser);
+#endif
+ if ( backend_plugin->plg_upgradedb != NULL ) {
+ return_value = (*backend_plugin->plg_upgradedb)( &pb );
+ } else {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ERROR: no upgradedb function defined for "
+ "%s\n", backend_plugin->plg_name, 0, 0 );
+ return_value = -1;
+ }
+ slapi_ch_free((void**)&myname );
+ return( return_value );
+}
+#endif
+
+
+static int
+slapd_exemode_dbtest()
+{
+ int return_value= 0;
+ Slapi_PBlock pb;
+ struct slapdplugin *plugin;
+
+ if (NULL == cmd_line_instance_name) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "dbtest: Required argument -n <instance name> missing\n", 0, 0, 0);
+ usage( myname, extraname );
+ exit(1);
+ }
+
+ mapping_tree_init();
+
+ plugin = lookup_plugin_by_instance_name(cmd_line_instance_name);
+ if (plugin == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "ERROR: Could not find backend '%s'.\n",
+ cmd_line_instance_name, 0, 0);
+ exit(1);
+ }
+
+ /* Make sure we aren't going to run slapd in
+ * a mode that is going to conflict with other
+ * slapd processes that are currently running
+ */
+ if ( add_new_slapd_process(slapd_exemode, db2ldif_dump_replica,
+ skip_db_protect_check) == -1 ) {
+
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Shutting down due to possible conflicts with other slapd processes\n",
+ 0, 0, 0 );
+ exit(1);
+ }
+
+ pb.pb_backend = NULL;
+ pb.pb_plugin = plugin;
+ pb.pb_instance_name = cmd_line_instance_name;
+ /* For dbtest, we do _not_ change identity (no setuid()) */
+ return_value= (*plugin->plg_dbtest)( &pb );
+ return return_value;
+}
+
+
+
+#ifdef LDAP_DEBUG
+/*
+ * Table to associate a string with a debug level.
+ */
+static struct slapd_debug_level_entry {
+ int dle_level; /* LDAP_DEBUG_XXX value */
+ const char *dle_string; /* string equivalent; NULL marks end of list */
+ char dle_hide;
+} slapd_debug_level_map[] = {
+ { LDAP_DEBUG_TRACE, "trace", 0 },
+ { LDAP_DEBUG_PACKETS, "packets", 0 },
+ { LDAP_DEBUG_ARGS, "arguments", 0 },
+ { LDAP_DEBUG_ARGS, "args", 1 },
+ { LDAP_DEBUG_CONNS, "connections", 0 },
+ { LDAP_DEBUG_CONNS, "conn", 1 },
+ { LDAP_DEBUG_CONNS, "conns", 1 },
+ { LDAP_DEBUG_BER, "ber", 0 },
+ { LDAP_DEBUG_FILTER, "filters", 0 },
+ { LDAP_DEBUG_CONFIG, "config", 0 },
+ { LDAP_DEBUG_ACL, "accesscontrol", 0 },
+ { LDAP_DEBUG_ACL, "acl", 1 },
+ { LDAP_DEBUG_ACL, "acls", 1 },
+ { LDAP_DEBUG_STATS, "stats", 0 },
+ { LDAP_DEBUG_STATS2, "stats2", 0 },
+ { LDAP_DEBUG_SHELL, "shell", 1 },
+ { LDAP_DEBUG_PARSE, "parsing", 0 },
+ { LDAP_DEBUG_HOUSE, "housekeeping", 0 },
+ { LDAP_DEBUG_REPL, "replication", 0 },
+ { LDAP_DEBUG_REPL, "repl", 1 },
+ { LDAP_DEBUG_ANY, "errors", 0 },
+ { LDAP_DEBUG_ANY, "ANY", 1 },
+ { LDAP_DEBUG_ANY, "error", 1 },
+ { LDAP_DEBUG_CACHE, "caches", 0 },
+ { LDAP_DEBUG_CACHE, "cache", 1 },
+ { LDAP_DEBUG_PLUGIN, "plugins", 0 },
+ { LDAP_DEBUG_PLUGIN, "plugin", 1 },
+ { LDAP_DEBUG_TIMING, "timing", 0 },
+ { LDAP_DEBUG_ACLSUMMARY,"accesscontrolsummary", 0 },
+ { LDAP_DEBUG_ALL_LEVELS,"ALL", 0 },
+ { 0, NULL, 0 }
+};
+
+
+
+/*
+ * Given a string represention of a debug level, map it to a integer value
+ * and return that value. -1 is returned upon error, with a message
+ * printed to stderr.
+ */
+static int
+slapd_debug_level_string2level( const char *s )
+{
+ int level, i;
+ char *cur, *next, *scopy;
+
+ level = 0;
+ cur = scopy = slapi_ch_strdup( s );
+
+ for ( cur = scopy; cur != NULL; cur = next ) {
+ if (( next = strchr( cur, '+' )) != NULL ) {
+ *next++ = '\0';
+ }
+
+ if ( isdigit( *cur )) {
+ level |= atoi( cur );
+ } else {
+ for ( i = 0; NULL != slapd_debug_level_map[i].dle_string; ++i ) {
+ if ( strcasecmp( cur, slapd_debug_level_map[i].dle_string )
+ == 0 ) {
+ level |= slapd_debug_level_map[i].dle_level;
+ break;
+ }
+ }
+
+ if ( NULL == slapd_debug_level_map[i].dle_string ) {
+ fprintf( stderr, "Unrecognized debug level \"%s\"\n", cur );
+ return -1;
+ }
+ }
+ }
+
+ slapi_ch_free( (void **)&scopy );
+
+ return level;
+}
+
+
+/*
+ * Print to stderr the string equivalent of level.
+ * The ANY level is omitted because it is always present.
+ */
+static void
+slapd_debug_level_log( int level )
+{
+ int i, count, len;
+ char *msg, *p;
+
+ level &= ~LDAP_DEBUG_ANY;
+
+ /* first pass: determine space needed for the debug level string */
+ len = 1; /* room for '\0' terminator */
+ count = 0;
+ for ( i = 0; NULL != slapd_debug_level_map[i].dle_string; ++i ) {
+ if ( !slapd_debug_level_map[i].dle_hide &&
+ slapd_debug_level_map[i].dle_level != LDAP_DEBUG_ALL_LEVELS
+ && 0 != ( level & slapd_debug_level_map[i].dle_level )) {
+ if ( count > 0 ) {
+ ++len; /* room for '+' character */
+ }
+ len += strlen( slapd_debug_level_map[i].dle_string );
+ ++count;
+ }
+ }
+
+ /* second pass: construct the debug level string */
+ p = msg = slapi_ch_malloc( len );
+ count = 0;
+ for ( i = 0; NULL != slapd_debug_level_map[i].dle_string; ++i ) {
+ if ( !slapd_debug_level_map[i].dle_hide &&
+ slapd_debug_level_map[i].dle_level != LDAP_DEBUG_ALL_LEVELS
+ && 0 != ( level & slapd_debug_level_map[i].dle_level )) {
+ if ( count > 0 ) {
+ *p++ = '+';
+ }
+ strcpy( p, slapd_debug_level_map[i].dle_string );
+ p += strlen( p );
+ ++count;
+ }
+ }
+
+ slapi_log_error( SLAPI_LOG_FATAL, SLAPD_VERSION_STR,
+ "%s: %s (%d)\n", "debug level", msg, level );
+ slapi_ch_free( (void **)&msg );
+}
+
+
+/*
+ * Display usage/help for the debug level flag (-d)
+ */
+static void
+slapd_debug_level_usage( void )
+{
+ int i;
+
+ fprintf( stderr, "Debug levels:\n" );
+ for ( i = 0; NULL != slapd_debug_level_map[i].dle_string; ++i ) {
+ if ( !slapd_debug_level_map[i].dle_hide
+ && slapd_debug_level_map[i].dle_level
+ != LDAP_DEBUG_ALL_LEVELS) {
+ fprintf( stderr, " %6d - %s%s\n",
+ slapd_debug_level_map[i].dle_level,
+ slapd_debug_level_map[i].dle_string,
+ ( 0 == ( slapd_debug_level_map[i].dle_level &
+ LDAP_DEBUG_ANY )) ? "" :
+ " (always logged)" );
+ }
+ }
+ fprintf( stderr, "To activate multiple levels, add the numeric"
+ " values together or separate the\n"
+ "values with a + character, e.g., all of the following"
+ " have the same effect:\n"
+ " -d connections+filters\n"
+ " -d 8+32\n"
+ " -d 40\n" );
+}
+#endif /* LDAP_DEBUG */
+