summaryrefslogtreecommitdiffstats
path: root/ldap/admin/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/admin/lib')
-rw-r--r--ldap/admin/lib/Makefile108
-rw-r--r--ldap/admin/lib/dsalib_conf.c213
-rw-r--r--ldap/admin/lib/dsalib_confs.c130
-rw-r--r--ldap/admin/lib/dsalib_db.c374
-rw-r--r--ldap/admin/lib/dsalib_debug.c73
-rw-r--r--ldap/admin/lib/dsalib_dn.c465
-rw-r--r--ldap/admin/lib/dsalib_filename.c95
-rw-r--r--ldap/admin/lib/dsalib_html.c201
-rw-r--r--ldap/admin/lib/dsalib_ldif.c374
-rw-r--r--ldap/admin/lib/dsalib_location.c142
-rw-r--r--ldap/admin/lib/dsalib_pw.c29
-rw-r--r--ldap/admin/lib/dsalib_tailf.c206
-rw-r--r--ldap/admin/lib/dsalib_updown.c702
-rw-r--r--ldap/admin/lib/dsalib_util.c1123
14 files changed, 4235 insertions, 0 deletions
diff --git a/ldap/admin/lib/Makefile b/ldap/admin/lib/Makefile
new file mode 100644
index 00000000..8aa9a705
--- /dev/null
+++ b/ldap/admin/lib/Makefile
@@ -0,0 +1,108 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# GNU Makefile for Directory Server Admin DLL/SO.
+#
+
+LDAP_SRC = ../..
+MCOM_ROOT = ../../../..
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+NSPR20=true # probably should be defined somewhere else (not sure where)
+
+OBJDEST = $(LDAP_ADMOBJDIR)
+LIBDIR = $(LDAP_LIBDIR)
+ALIBDIR = $(LDAP_ADMLIBDIR)
+BINDIR=$(LDAP_ADMIN_BIN_RELDIR)
+
+include $(MCOM_ROOT)/ldapserver/nsdefs.mk
+include $(MCOM_ROOT)/ldapserver/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+
+SRCS = dsalib_location.c dsalib_debug.c dsalib_updown.c dsalib_tailf.c \
+ dsalib_ldif.c dsalib_db.c dsalib_conf.c dsalib_html.c \
+ dsalib_filename.c dsalib_util.c dsalib_dn.c dsalib_confs.c dsalib_pw.c
+
+PWDOBJ=$(OBJDIR)/lib/libpwdstorage/ssha_pwd.o
+
+OBJS1 = $(addprefix $(OBJDEST)/, $(subst .c,.o,$(SRCS)))
+OBJS = $(OBJS1) $(PWDOBJ)
+
+INCLUDES += -I$(LDAP_SRC)/admin/include
+ifdef FORTEZZA
+INCLUDES += -I$(MCOM_ROOT)/lib
+endif
+
+EXTRA_LIBS += $(LDAP_COMMON_LIBS) $(SECURITYLINK) $(NSPRLINK)
+
+LIBS= $(LDAP_ADMDLLDIR)/libds_admin$(DLL_PRESUF).$(DLL_SUFFIX)
+ifeq ($(ARCH), WINNT)
+IMPLIB= /IMPLIB:$(LDAP_ADMLIBDIR)/libds_admin.lib
+MAPFILE= /MAP:$(LDAP_ADMLIBDIR)/libds_admin.map
+EXTRA_LIBS_DEP += $(LDAP_COMMON_LIBS_DEP) $(LDAP_LIBLDIF_DEP)
+#EXTRA_LIBS += $(LDAP_COMMON_LIBS) $(LDAP_LIBLDIF) $(LDAP_SDK_LIBLDAP_DLL) \
+# $(ADMINUTIL_LINK) $(SECURITYLINK) $(NSPRLINK)
+else # WINNT
+ifdef FORTEZZA
+# libci.a needs to be recompiled with the -Z option on HPUX, until then,
+# we'll link libci.a with the executables which need it -atom
+ifneq ($(ARCH), HPUX)
+EXTRA_LIBS_DEP += $(FORTEZZA_DRIVER)
+EXTRA_LIBS += $(FORTEZZA_DRIVER)
+endif # !HPUX
+endif # FORTEZZA
+endif # WINNT
+
+ifeq ($(ARCH), Linux)
+# XXXsspitzer: we do this so that cgi's the link against libds_admin.so
+# will be able to find libns-dshttpd.so at run time. Only platforms that
+# build with gcc need to do this.
+RPATHFLAG_EXTRAS+=:../..:..
+endif # Linux
+
+ifeq ($(ARCH), AIX)
+EXTRA_LIBS_DEP += $(LDAPSDK_DEP)
+#EXTRA_LIBS += $(LDAP_SDK_LIBLDAP_DLL) $(SECURITYLINK) $(ADMINUTIL_LINK) $(NSPRLINK) $(DBMLINK)
+LD=ld -noquiet
+endif
+
+# for Solaris, our most common unix build platform, we check for undefined symbols
+# at link time so we don't catch them at run time. To do this, we set the -z defs
+# flag. We also have to add -lc to the end because, even though ld and cc link with
+# it implicitly, -z defs will throw errors if we do not link with it explicitly
+ifeq ($(ARCH), SOLARIS)
+LINK_DLL += -z defs
+EXTRA_LIBS += -lc
+endif
+
+all: $(LIBS) $(LDAP_ADMDLL_RELDLLS)
+
+$(LIBS): $(OBJDEST) $(LDAP_ADMDLLDIR) $(LDAP_ADMLIBDIR) $(OBJS) $(EXTRA_LIBS_DEP)
+ $(LINK_DLL) $(IMPLIB) $(MAPFILE) $(EXTRA_LIBS)
+
+ifeq ($(ARCH), WINNT)
+$(LDAP_ADMDLL_RELDLLS): $(LIBS) $(LDAP_ADMDLL_RELDIRS)
+ cp $< $@
+
+endif
+
+veryclean: clean
+
+clean:
+ -$(RM) $(OBJS1)
+ -$(RM) $(LIBS)
+ifeq ($(ARCH), WINNT)
+ -$(RM) $(IMPLIB)
+endif
+
+$(OBJS1): $(OBJDEST)/%.o: %.c
+ $(CC) -c $(NONSHARED) $(CFLAGS) $(MCC_INCLUDE) $(OFFLAG)$(OBJDEST)/$*.o $*.c
+ifdef USE_LINT
+ $(LINT) $(LINTCCFLAGS) $(DEFS) $(MCC_SERVER) $(INCLUDES) $(MCC_INCLUDE) $*.c > $(OBJDEST)/$*.ln 2>&1
+endif
diff --git a/ldap/admin/lib/dsalib_conf.c b/ldap/admin/lib/dsalib_conf.c
new file mode 100644
index 00000000..cc331619
--- /dev/null
+++ b/ldap/admin/lib/dsalib_conf.c
@@ -0,0 +1,213 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#include <process.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dsalib.h"
+#include <ldaplog.h>
+#include "portable.h"
+#include <ctype.h>
+
+#define CONF_FILE_NAME "config/dse.ldif"
+#define CONF_SUFFIX "cn=config"
+
+DS_EXPORT_SYMBOL char *
+ds_get_var_name(int varnum)
+{
+ if ( (varnum >= DS_CFG_MAX) || (varnum < 0) )
+ return(NULL); /* failure */
+ return(ds_cfg_info[varnum].dci_varname);
+}
+
+/*
+ * Get config info.
+ */
+DS_EXPORT_SYMBOL char **
+ds_get_config(int type)
+{
+ char conffile[PATH_MAX];
+ char *root;
+ FILE *sf = NULL;
+ char **conf_list = NULL;
+
+ if ( (type != DS_REAL_CONFIG) && (type != DS_TMP_CONFIG) ) {
+ ds_send_error("Invalid config file type.", 0);
+ return(NULL);
+ }
+
+ if ( (root = ds_get_install_root()) == NULL ) {
+ ds_send_error("Cannot find server root directory.", 0);
+ return(NULL);
+ }
+
+ sprintf(conffile, "%s/%s", root, CONF_FILE_NAME);
+
+ if ( !(sf = fopen(conffile, "r")) ) {
+ ds_send_error("could not read config file.", 1);
+ return(NULL);
+ }
+
+ conf_list = ds_get_conf_from_file(sf);
+
+ fclose(sf);
+ if (!conf_list) {
+ ds_send_error("failed to read the config file successfully.", 0);
+ return(NULL);
+ }
+ return(conf_list);
+}
+
+/*
+ * NOTE: the ordering of the following array elements must be kept in sync
+ * with the ordering of the #defines in ../include/dsalib.h.
+ */
+struct ds_cfg_info ds_cfg_info[] = {
+{"nsslapd-errorlog-level" },
+{"nsslapd-referral" },
+{"nsslapd-auditlog" },
+{"nsslapd-localhost" },
+{"nsslapd-port" },
+{"nsslapd-security" },
+{"nsslapd-secureport" },
+{"nsslapd-ssl3ciphers"},
+{"passwordstoragescheme"},
+{"nsslapd-accesslog"},
+{"nsslapd-errorlog"},
+{"nsslapd-rootdn"},
+{"nsslapd-rootpwstoragescheme"},
+{"nsslapd-suffix"},
+{"nsslapd-localuser"},
+{0}
+};
+
+/*
+ * Open the config file and look for option "option". Return its
+ * value, or NULL if the option was not found.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_config_value( int option )
+{
+ char **all, *value;
+ int i;
+ char *attr = ds_get_var_name(option);
+
+ if (attr == NULL)
+ return NULL;
+
+ all = ds_get_config( DS_REAL_CONFIG );
+ if ( all == NULL ) {
+ return NULL;
+ }
+ for ( i = 0; all[ i ] != NULL; i++ ) {
+ if (( value = strchr( all[ i ], ':' )) != NULL ) {
+ *value = '\0';
+ ++value;
+ while (*value && isspace(*value))
+ ++value;
+ }
+ if ( !strcasecmp( attr, all[ i ] )) {
+ return strdup( value );
+ }
+ }
+ return NULL;
+}
+
+static size_t
+count_quotes (const char* s)
+{
+ size_t count = 0;
+ const char* t = s;
+ if (t) while ((t = strpbrk (t, "\"\\")) != NULL) {
+ ++count;
+ ++t;
+ }
+ return count;
+}
+
+DS_EXPORT_SYMBOL char*
+ds_enquote_config_value (int paramnum, char* s)
+{
+ char* result;
+ char* brkcharset = "\"\\ \t\r\n";
+ char *encoded_quote = "22"; /* replace quote with \22 */
+ int encoded_quote_len = strlen(encoded_quote);
+ char *begin = s;
+ if (*s && ! strpbrk (s, brkcharset) &&
+ ! (paramnum == DS_AUDITFILE || paramnum == DS_ACCESSLOG ||
+#if defined( XP_WIN32 )
+ paramnum == DS_SUFFIX ||
+#endif
+ paramnum == DS_ERRORLOG)) {
+ result = s;
+ } else {
+ char* t = malloc (strlen (s) + count_quotes (s) + 3);
+ result = t;
+ *t++ = '"';
+ while (*s) {
+ switch (*s) {
+
+ case '"':
+ /* convert escaped quotes by replacing the quote with
+ escape code e.g. 22 so that \" is converted to \22 "*/
+ if ((s > begin) && (*(s - 1) == '\\'))
+ {
+ strcpy(t, encoded_quote);
+ t += encoded_quote_len;
+ }
+ else /* unescaped ", just replace with \22 "*/
+ {
+ *t++ = '\\';
+ strcpy(t, encoded_quote);
+ t += encoded_quote_len;
+ }
+ ++s;
+ break;
+
+ default:
+ *t++ = *s++; /* just copy it */
+ break;
+ }
+ }
+ *t++ = '"';
+ *t = '\0';
+ }
+ return result;
+}
+
+DS_EXPORT_SYMBOL char*
+ds_DNS_to_DN (char* DNS)
+{
+ static const char* const RDN = "dc=";
+ char* DN;
+ char* dot;
+ size_t components;
+ if (DNS == NULL || *DNS == '\0') {
+ return strdup ("");
+ }
+ components = 1;
+ for (dot = strchr (DNS, '.'); dot != NULL; dot = strchr (dot + 1, '.')) {
+ ++components;
+ }
+ DN = malloc (strlen (DNS) + (components * strlen(RDN)) + 1);
+ strcpy (DN, RDN);
+ for (dot = strchr (DNS, '.'); dot != NULL; dot = strchr (dot + 1, '.')) {
+ *dot = '\0';
+ strcat (DN, DNS);
+ strcat (DN, ",");
+ strcat (DN, RDN);
+ DNS = dot + 1;
+ *dot = '.';
+ }
+ strcat (DN, DNS);
+ dn_normalize (DN);
+ return DN;
+}
diff --git a/ldap/admin/lib/dsalib_confs.c b/ldap/admin/lib/dsalib_confs.c
new file mode 100644
index 00000000..ccaf8bd9
--- /dev/null
+++ b/ldap/admin/lib/dsalib_confs.c
@@ -0,0 +1,130 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * Some of the simple conf stuff here. Must not call any
+ * libadmin functions! This is needed by ds_config.c
+ */
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+#include "dsalib.h"
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ldif.h>
+#include <ctype.h>
+#include "plstr.h"
+
+/*
+ * Read the configuration info into a null-terminated list of strings.
+ */
+DS_EXPORT_SYMBOL char **
+ds_get_conf_from_file(FILE *conf)
+{
+ static char config_entry[] = "dn: cn=config";
+ static int cfg_ent_len = sizeof(config_entry)-1;
+ int listsize = 0;
+ char **conf_list = NULL;
+ char *entry = 0;
+ int lineno = 0;
+
+ while (entry = ldif_get_entry(conf, &lineno)) {
+ char *begin = entry;
+ if (!PL_strncasecmp(entry, config_entry, cfg_ent_len)) {
+ char *line = entry;
+ while (line = ldif_getline(&entry)) {
+ listsize++;
+ conf_list = (char **) realloc(conf_list,
+ ((listsize + 1) * sizeof(char *)));
+ conf_list[listsize - 1] = strdup(line);
+ conf_list[listsize] = NULL; /* always null terminated */
+ }
+ }
+ free(begin);
+ }
+
+ return(conf_list);
+}
+
+/*
+ * Returns 1 if parm is in confline else 0
+ */
+static int
+ds_parm_in_line(char *confline, char *parm)
+{
+ int parm_size;
+
+ if ( confline == NULL )
+ return(0);
+ if ( parm == NULL )
+ return(0);
+ parm_size = strlen(parm);
+ if ( parm_size == (int)NULL )
+ return(0);
+ if ( PL_strncasecmp(confline, parm, parm_size) == 0 )
+ if ( ((int) strlen(confline)) > parm_size )
+ if ( confline[parm_size] == ':' )
+ return(1);
+ return(0);
+}
+
+/*
+ * Gets the string that corresponds to the parameter supplied from the
+ * list of config lines. Returns a malloc'd string.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_value(char **ds_config, char *parm, int phase, int occurance)
+{
+ char *line;
+ int line_num = 0;
+ int cur_phase = 0;
+ int cur_occurance = 0;
+
+ if ( (parm == NULL) || (ds_config == NULL) )
+ return(NULL);
+ if ( (phase < 0) || (occurance < 1) )
+ return(NULL);
+ line = ds_config[line_num];
+ while ( line != NULL ) {
+ if ( ds_parm_in_line(line, "database") )
+ cur_phase++;
+ if ( ds_parm_in_line(line, parm) ) { /* found it */
+ if ( phase == cur_phase )
+ if ( ++cur_occurance == occurance ) {
+ /*
+ * Use ldif_parse_line() so continuation markers are
+ * handled correctly, etc.
+ */
+ char *errmsg, *type = NULL, *value = NULL, *tmpvalue = NULL;
+ int ldif_rc, tmpvlen = 0;
+ char *tmpline = strdup(line);
+
+ if ( NULL == tmpline ) {
+ ds_send_error(
+ "ds_get_value() failed: strdup() returned NULL\n",
+ 1 /* print errno */ );
+ return(NULL);
+ }
+
+ ldif_rc = ldif_parse_line( tmpline, &type, &tmpvalue,
+ &tmpvlen, &errmsg );
+ if (ldif_rc < 0) {
+ ds_send_error(errmsg, 0 /* do not print errno */);
+ } else if (ldif_rc == 0) { /* value returned in place */
+ value = strdup(tmpvalue);
+ } else { /* malloc'd value */
+ value = tmpvalue;
+ }
+ free(tmpline);
+ return value;
+ }
+ }
+ line_num++;
+ line = ds_config[line_num];
+ }
+ return(NULL);
+}
diff --git a/ldap/admin/lib/dsalib_db.c b/ldap/admin/lib/dsalib_db.c
new file mode 100644
index 00000000..02d9498f
--- /dev/null
+++ b/ldap/admin/lib/dsalib_db.c
@@ -0,0 +1,374 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#endif
+#include "dsalib.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined( XP_WIN32 )
+#include <dirent.h>
+#include <unistd.h>
+#else
+#define popen _popen
+#define pclose _pclose
+#endif
+#include "portable.h"
+
+/*
+ * Get a listing of backup directories
+ * Return NULL for errors and a NULL list for an empty list.
+ */
+
+DS_EXPORT_SYMBOL char **
+ds_get_bak_dirs()
+{
+ char format_str[PATH_MAX];
+ char *root;
+ int i = 0;
+ char **bak_dirs = NULL;
+
+ if ( (root = ds_get_install_root()) == NULL )
+ {
+ ds_send_error("Cannot find server root directory.", 0);
+ return(bak_dirs);
+ }
+
+ sprintf( format_str, "%s%cbak", root, FILE_SEP );
+ bak_dirs = ds_get_file_list( format_str );
+ if( bak_dirs )
+ {
+ while( bak_dirs[i] != NULL )
+ {
+ /* Prepend the filename with the install root */
+ char filename[PATH_MAX];
+ sprintf( filename, "%s%cbak%c%s", root, FILE_SEP,
+ FILE_SEP, bak_dirs[i] );
+ free( bak_dirs[i] );
+ bak_dirs[i] = strdup( filename );
+#if defined( XP_WIN32 )
+ ds_dostounixpath( bak_dirs[i] );
+#endif
+ i++;
+ }
+ }
+
+ return(bak_dirs);
+}
+
+/*
+ * Restore a database based on a backup directory name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_bak2db(char *file)
+{
+ char startup_line[BIG_LINE];
+ char statfile[PATH_MAX];
+ char *tmp_dir;
+ char *root;
+ int haderror = 0;
+ int error = -1;
+ int status;
+ FILE *sf = NULL;
+ struct stat fstats;
+
+ if ( file == NULL ) {
+ return DS_NULL_PARAMETER;
+ }
+ status = ds_get_updown_status();
+ if ( status == DS_SERVER_UP ) {
+ return DS_SERVER_MUST_BE_DOWN;
+ }
+ if ( (root = ds_get_install_root()) == NULL ) {
+ return DS_NO_SERVER_ROOT;
+ }
+
+ if ( file[strlen(file) - 1] == '\n' ) /* strip out returns */
+ file[strlen(file) - 1] = '\0';
+
+ if( stat( file, &fstats ) == -1 && errno == ENOENT ) {
+ return DS_CANNOT_OPEN_BACKUP_FILE;
+ } else if( !(fstats.st_mode & S_IFDIR) ) {
+ return DS_NOT_A_DIRECTORY;
+ }
+
+ tmp_dir = ds_get_tmp_dir();
+ sprintf(statfile, "%s%cbak2db.%d", tmp_dir, FILE_SEP, (int)getpid());
+ sprintf(startup_line,
+ "%s%cbak2db "
+ "%s%s%s > "
+ "%s%s%s 2>&1",
+ root, FILE_SEP,
+ ENQUOTE, file, ENQUOTE,
+ ENQUOTE, statfile, ENQUOTE );
+ alter_startup_line(startup_line);
+ fflush(0);
+ error = system(startup_line);
+ fflush(0);
+ if ( error == -1 ) {
+ return DS_CANNOT_EXEC;
+ }
+ fflush(0);
+ if( !(sf = fopen(statfile, "r")) ) {
+ return DS_CANNOT_OPEN_STAT_FILE;
+ }
+
+ while ( fgets(startup_line, BIG_LINE, sf) ) {
+ if ((strstr(startup_line, "- Restoring file")) ||
+ (strstr(startup_line, "- Checkpointing"))) {
+ ds_show_message(startup_line);
+ } else {
+ haderror = 1;
+ ds_send_error(startup_line, 0);
+ }
+ }
+
+ fclose(sf);
+ unlink(statfile);
+
+ if ( haderror )
+ return DS_UNKNOWN_ERROR;
+ return 0;
+}
+
+/*
+ * Create a backup based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_db2bak(char *file)
+{
+ char startup_line[BIG_LINE];
+ char statfile[PATH_MAX];
+ char *tmp_dir;
+ char *root;
+ int haderror = 0;
+ int error = -1;
+ FILE *sf = NULL;
+ int lite = 0;
+#ifdef XP_WIN32
+ time_t ltime;
+#endif
+
+ if ( (root = ds_get_install_root()) == NULL ) {
+ return DS_NO_SERVER_ROOT;
+ }
+
+ if ( (file == NULL) || (strlen(file) == 0) )
+ file = NULL;
+
+ tmp_dir = ds_get_tmp_dir();
+ sprintf(statfile, "%s%cdb2bak.%d", tmp_dir, FILE_SEP, (int)getpid());
+
+
+#if defined( XP_WIN32 )
+ if( file == NULL )
+ {
+ file = malloc( BIG_LINE );
+
+ time( &ltime );
+ sprintf( file, "%s", ctime( &ltime ) );
+ ds_timetofname( file );
+ }
+
+ /* Check if the directory exists or can be created */
+ if ( !ds_file_exists( file ) ) {
+ char *errmsg = ds_mkdir_p( file, NEWDIR_MODE );
+ if( errmsg != NULL ) {
+/* ds_send_error(errmsg, 10);
+ */
+ return DS_CANNOT_CREATE_DIRECTORY;
+ }
+ }
+#endif
+
+/* DBDB: note on the following line.
+ * Originally this had quotes round the directory name.
+ * I found that this made the script not work becuase
+ * a path of the form "foo"/bar/"baz" was passed to slapd.
+ * the c runtime didn't like this. Perhaps there's a simple
+ * solution, but for now I've modified this line here to
+ * not quote the directory name. This means that backup
+ * directories can't have spaces in them.
+ */
+
+
+ sprintf(startup_line,
+ "%s%cdb2bak "
+ "%s%s%s > "
+ "%s%s%s 2>&1",
+ root, FILE_SEP,
+ ENQUOTE,
+ (file == NULL) ? "" : file,
+ ENQUOTE,
+ ENQUOTE, statfile, ENQUOTE);
+
+ PATH_FOR_PLATFORM( startup_line );
+ alter_startup_line(startup_line);
+ fflush(0);
+ error = system(startup_line);
+ if ( error == -1 ) {
+ return DS_CANNOT_EXEC;
+ }
+ if( !(sf = fopen(statfile, "r")) ) {
+ return DS_CANNOT_OPEN_STAT_FILE;
+ }
+
+ while ( fgets(startup_line, BIG_LINE, sf) ) {
+ if (strstr(startup_line, " - Backing up file") ||
+ strstr(startup_line, " - Checkpointing database")) {
+ ds_show_message(startup_line);
+ } else {
+ haderror = 1;
+ if (strstr ( startup_line, "restricted mode")) {
+ lite = 1;
+ }
+ ds_send_error(startup_line, 0);
+ }
+ }
+ fclose(sf);
+ unlink(statfile);
+
+ if ( lite && haderror )
+ return DS_HAS_TOBE_READONLY_MODE;
+
+ if ( haderror )
+ return DS_UNKNOWN_ERROR;
+ return 0;
+}
+
+static void
+process_and_report( char *line, int line_size, FILE *cmd )
+{
+ while(fgets(line, line_size, cmd)) {
+ /* Strip off line feeds */
+ int ind = strlen( line ) - 1;
+ while ( (ind >= 0) &&
+ ((line[ind] == '\n') ||
+ (line[ind] == '\r')) ) {
+ line[ind] = 0;
+ ind--;
+ }
+ if ( ind < 1 ) {
+ continue;
+ }
+ ds_send_status(line);
+ }
+}
+
+static int exec_and_report( char *startup_line )
+{
+ FILE *cmd = NULL;
+ char line[BIG_LINE];
+ int haderror = 0;
+
+ PATH_FOR_PLATFORM( startup_line );
+ alter_startup_line(startup_line);
+
+ /*
+ fprintf( stdout, "Launching <%s>\n", startup_line );
+ */
+
+ fflush(0);
+ cmd = popen(startup_line, "r");
+ if(!cmd) {
+ return DS_CANNOT_EXEC;
+ }
+ process_and_report( line, sizeof(line), cmd );
+ pclose(cmd);
+
+ /*
+ ** The VLV indexing code prints OK,
+ ** if the index was successfully created.
+ */
+ if (strcmp(line,"OK")==0) {
+ haderror = 0;
+ } else {
+ haderror = DS_UNKNOWN_ERROR;
+ }
+
+ return haderror;
+}
+
+/*
+ * Create a vlv index
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_vlvindex(char **backendList, char **vlvList)
+{
+ char startup_line[BIG_LINE];
+ char *root;
+ char *instroot;
+ char **vlvc = NULL;
+
+
+ root = ds_get_server_root();
+ instroot = ds_get_install_root();
+ if ( (root == NULL) || (instroot == NULL) ) {
+ return DS_NO_SERVER_ROOT;
+ }
+
+ sprintf(startup_line, "%s/bin/slapd/server/%s db2index "
+ "-D %s%s/%s "
+ "-n %s ",
+ root, SLAPD_NAME,
+ ENQUOTE, instroot, ENQUOTE,
+ backendList[0]);
+
+
+ /* Create vlv TAG */
+ vlvc=vlvList;
+ while( *vlvc != NULL ) {
+ sprintf( startup_line, "%s -T %s%s%s", startup_line,"\"",*vlvc,"\"" );
+ vlvc++;
+ }
+
+ return exec_and_report( startup_line );
+}
+
+/*
+ * Create one or more indexes
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_addindex(char **attrList, char *backendName)
+{
+ char startup_line[BIG_LINE];
+ char *root;
+ char *instroot;
+
+ root = ds_get_server_root();
+ instroot = ds_get_install_root();
+
+ if ( (root == NULL) || (instroot == NULL) ) {
+ return DS_NO_SERVER_ROOT;
+ }
+
+ sprintf(startup_line, "%s/bin/slapd/server/%s db2index "
+ "-D %s%s%s "
+ "-n %s",
+ root, SLAPD_NAME,
+ ENQUOTE, instroot, ENQUOTE,
+ backendName);
+
+ while( *attrList != NULL ) {
+ sprintf( startup_line, "%s -t %s", startup_line, *attrList );
+ attrList++;
+ }
+
+ return exec_and_report( startup_line );
+}
diff --git a/ldap/admin/lib/dsalib_debug.c b/ldap/admin/lib/dsalib_debug.c
new file mode 100644
index 00000000..4819a94d
--- /dev/null
+++ b/ldap/admin/lib/dsalib_debug.c
@@ -0,0 +1,73 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+#include "dsalib.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined( XP_WIN32 )
+int ldap_debug = 0;
+#endif
+
+DS_EXPORT_SYMBOL void
+ds_log_env(char **envp)
+{
+ FILE *file;
+ char admin_logfile[PATH_MAX], *tmp_dir;
+
+ tmp_dir = ds_get_tmp_dir();
+ memset( admin_logfile, 0, sizeof( admin_logfile ) );
+ strcat( admin_logfile, tmp_dir );
+#if defined( XP_WIN32 )
+ if( tmp_dir )
+ {
+ free( tmp_dir );
+ tmp_dir = NULL;
+ }
+#endif
+ strcat( admin_logfile, "/admin.log");
+
+ file = fopen(admin_logfile, "a+");
+ if (file != NULL) {
+ int i;
+ for ( i = 0; envp[i] != (char *) 0; i++ ) {
+ char envstr[200];
+
+ sprintf(envstr, "%s\n", envp[i]);
+ fwrite(envstr, strlen(envstr), 1, file);
+ }
+ fclose(file);
+ }
+}
+
+DS_EXPORT_SYMBOL void
+ds_log_debug_message(char *msg)
+{
+ FILE *file;
+ char admin_logfile[PATH_MAX], *tmp_dir;
+
+ tmp_dir = ds_get_tmp_dir();
+ memset( admin_logfile, 0, sizeof( admin_logfile ) );
+ strcat( admin_logfile, tmp_dir );
+#if defined( XP_WIN32 )
+ if( tmp_dir )
+ {
+ free( tmp_dir );
+ tmp_dir = NULL;
+ }
+#endif
+ strcat( admin_logfile, "/admin.log");
+
+ file = fopen(admin_logfile, "a+");
+ if (file != NULL) {
+ fwrite(msg, strlen(msg), 1, file);
+ fclose(file);
+ }
+}
+
diff --git a/ldap/admin/lib/dsalib_dn.c b/ldap/admin/lib/dsalib_dn.c
new file mode 100644
index 00000000..d7de36d9
--- /dev/null
+++ b/ldap/admin/lib/dsalib_dn.c
@@ -0,0 +1,465 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#if defined( XP_WIN32 )
+#include <windows.h>
+#else
+#include <sys/types.h>
+#endif
+#include <string.h>
+#include "dsalib.h"
+#include "portable.h"
+#include <stdlib.h>
+
+#define DNSEPARATOR(c) (c == ',' || c == ';')
+#define SEPARATOR(c) (c == ',' || c == ';' || c == '+')
+#define SPACE(c) (c == ' ' || c == '\n')
+#define NEEDSESCAPE(c) (c == '\\' || c == '"')
+#define B4TYPE 0
+#define INTYPE 1
+#define B4EQUAL 2
+#define B4VALUE 3
+#define INVALUE 4
+#define INQUOTEDVALUE 5
+#define B4SEPARATOR 6
+
+DS_EXPORT_SYMBOL char*
+dn_normalize( char *dn )
+{
+ char *d, *s;
+ int state, gotesc;
+
+ /* Debug( LDAP_DEBUG_TRACE, "=> dn_normalize \"%s\"\n", dn, 0, 0 ); */
+
+ gotesc = 0;
+ state = B4TYPE;
+ for ( d = s = dn; *s; s++ ) {
+ switch ( state ) {
+ case B4TYPE:
+ if ( ! SPACE( *s ) ) {
+ state = INTYPE;
+ *d++ = *s;
+ }
+ break;
+ case INTYPE:
+ if ( *s == '=' ) {
+ state = B4VALUE;
+ *d++ = *s;
+ } else if ( SPACE( *s ) ) {
+ state = B4EQUAL;
+ } else {
+ *d++ = *s;
+ }
+ break;
+ case B4EQUAL:
+ if ( *s == '=' ) {
+ state = B4VALUE;
+ *d++ = *s;
+ } else if ( ! SPACE( *s ) ) {
+ /* not a valid dn - but what can we do here? */
+ *d++ = *s;
+ }
+ break;
+ case B4VALUE:
+ if ( *s == '"' ) {
+ state = INQUOTEDVALUE;
+ *d++ = *s;
+ } else if ( ! SPACE( *s ) ) {
+ state = INVALUE;
+ *d++ = *s;
+ }
+ break;
+ case INVALUE:
+ if ( !gotesc && SEPARATOR( *s ) ) {
+ while ( SPACE( *(d - 1) ) )
+ d--;
+ state = B4TYPE;
+ if ( *s == '+' ) {
+ *d++ = *s;
+ } else {
+ *d++ = ',';
+ }
+ } else if ( gotesc && !NEEDSESCAPE( *s ) &&
+ !SEPARATOR( *s ) ) {
+ *--d = *s;
+ d++;
+ } else {
+ *d++ = *s;
+ }
+ break;
+ case INQUOTEDVALUE:
+ if ( !gotesc && *s == '"' ) {
+ state = B4SEPARATOR;
+ *d++ = *s;
+ } else if ( gotesc && !NEEDSESCAPE( *s ) ) {
+ *--d = *s;
+ d++;
+ } else {
+ *d++ = *s;
+ }
+ break;
+ case B4SEPARATOR:
+ if ( SEPARATOR( *s ) ) {
+ state = B4TYPE;
+ if ( *s == '+' ) {
+ *d++ = *s;
+ } else {
+ *d++ = ',';
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if ( *s == '\\' ) {
+ gotesc = 1;
+ } else {
+ gotesc = 0;
+ }
+ }
+ *d = '\0';
+
+ /* Debug( LDAP_DEBUG_TRACE, "<= dn_normalize \"%s\"\n", dn, 0, 0 ); */
+ return( dn );
+}
+
+DS_EXPORT_SYMBOL int
+dn_issuffix(
+ char *dn,
+ char *suffix
+)
+{
+ int dnlen, suffixlen;
+
+ if ( dn == NULL ) {
+ return( 0 );
+ }
+
+ suffixlen = strlen( suffix );
+ dnlen = strlen( dn );
+
+ if ( suffixlen > dnlen ) {
+ return( 0 );
+ }
+
+ return( strcasecmp( dn + dnlen - suffixlen, suffix ) == 0 );
+}
+
+DS_EXPORT_SYMBOL char*
+ds_dn_expand (char* dn)
+{
+ char* edn;
+ size_t i = 0;
+ char* s;
+ int state = B4TYPE;
+ int gotesc = 0;
+
+ if (dn == NULL) return NULL;
+ edn = strdup (dn);
+ for (s = dn; *s != '\0'; ++s, ++i) {
+ switch (state) {
+ case B4TYPE:
+ if ( ! SPACE (*s)) {
+ state = INTYPE;
+ }
+ break;
+ case INTYPE:
+ if (*s == '=') {
+ state = B4VALUE;
+ } else if (SPACE (*s)) {
+ state = B4EQUAL;
+ }
+ break;
+ case B4EQUAL:
+ if (*s == '=') {
+ state = B4VALUE;
+ }
+ break;
+ case B4VALUE:
+ if (*s == '"') {
+ state = INQUOTEDVALUE;
+ } else if ( ! SPACE (*s)) {
+ state = INVALUE;
+ }
+ break;
+ case INQUOTEDVALUE:
+ if (gotesc) {
+ if ( ! NEEDSESCAPE (*s)) {
+ --i;
+ memmove (edn+i, edn+i+1, strlen (edn+i));
+ }
+ } else {
+ if (*s == '"') {
+ state = B4SEPARATOR;
+ }
+ }
+ break;
+ case INVALUE:
+ if (gotesc) {
+ if ( ! NEEDSESCAPE (*s) && ! SEPARATOR (*s)) {
+ --i;
+ memmove (edn+i, edn+i+1, strlen (edn+i));
+ }
+ break;
+ }
+ case B4SEPARATOR:
+ if (SEPARATOR (*s)) {
+ state = B4TYPE;
+ if ( ! SPACE (s[1])) {
+ /* insert a space following edn[i] */
+ edn = (char*) realloc (edn, strlen (edn)+2);
+ ++i;
+ memmove (edn+i+1, edn+i, strlen (edn+i)+1);
+ edn[i] = ' ';
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ gotesc = (*s == '\\');
+ }
+ return edn;
+}
+
+int
+hexchar2int( char c )
+{
+ if ( '0' <= c && c <= '9' ) {
+ return( c - '0' );
+ }
+ if ( 'a' <= c && c <= 'f' ) {
+ return( c - 'a' + 10 );
+ }
+ if ( 'A' <= c && c <= 'F' ) {
+ return( c - 'A' + 10 );
+ }
+ return( -1 );
+}
+
+/*
+ * substr_dn_normalize - map a DN to a canonical form.
+ * The DN is read from *dn through *(end-1) and normalized in place.
+ * The new end is returned; that is, the canonical form is in
+ * *dn through *(the_return_value-1).
+ */
+
+/* The goals of this function are:
+ * 1. be compatible with previous implementations. Especially, enable
+ * a server running this code to find database index keys that were
+ * computed by Directory Server 3.0 with a prior version of this code.
+ * 2. Normalize in place; that is, avoid allocating memory to contain
+ * the canonical form.
+ * 3. eliminate insignificant differences; that is, any two DNs are
+ * not significantly different if and only if their canonical forms
+ * are identical (ignoring upper/lower case).
+ * 4. handle a DN in the syntax defined by RFC 2253.
+ * 5. handle a DN in the syntax defined by RFC 1779.
+ *
+ * Goals 3 through 5 are not entirely achieved by this implementation,
+ * because it can't be done without violating goal 1. Specifically,
+ * DNs like cn="a,b" and cn=a\,b are not mapped to the same canonical form,
+ * although they're not significantly different. Likewise for any pair
+ * of DNs that differ only in their choice of quoting convention.
+ * A previous version of this code changed all DNs to the most compact
+ * quoting convention, but that violated goal 1, since Directory Server
+ * 3.0 did not.
+ *
+ * Also, this implementation handles the \xx convention of RFC 2253 and
+ * consequently violates RFC 1779, according to which this type of quoting
+ * would be interpreted as a sequence of 2 numerals (not a single byte).
+ */
+
+DS_EXPORT_SYMBOL char *
+dn_normalize_convert( char *dn )
+{
+ /* \xx is changed to \c.
+ \c is changed to c, unless this would change its meaning.
+ All values that contain 2 or more separators are "enquoted";
+ all other values are not enquoted.
+ */
+ char *value, *value_separator;
+ char *d, *s;
+ char *end;
+
+ int gotesc = 0;
+ int state = B4TYPE;
+ if (NULL == dn)
+ return dn;
+
+ end = dn + strlen(dn);
+ for ( d = s = dn; s != end; s++ ) {
+ switch ( state ) {
+ case B4TYPE:
+ if ( ! SPACE( *s ) ) {
+ state = INTYPE;
+ *d++ = *s;
+ }
+ break;
+ case INTYPE:
+ if ( *s == '=' ) {
+ state = B4VALUE;
+ *d++ = *s;
+ } else if ( SPACE( *s ) ) {
+ state = B4EQUAL;
+ } else {
+ *d++ = *s;
+ }
+ break;
+ case B4EQUAL:
+ if ( *s == '=' ) {
+ state = B4VALUE;
+ *d++ = *s;
+ } else if ( ! SPACE( *s ) ) {
+ /* not a valid dn - but what can we do here? */
+ *d++ = *s;
+ }
+ break;
+ case B4VALUE:
+ if ( *s == '"' || ! SPACE( *s ) ) {
+ value_separator = NULL;
+ value = d;
+ state = ( *s == '"' ) ? INQUOTEDVALUE : INVALUE;
+ *d++ = *s;
+ }
+ break;
+ case INVALUE:
+ if ( gotesc ) {
+ if ( SEPARATOR( *s ) ) {
+ if ( value_separator ) value_separator = dn;
+ else value_separator = d;
+ } else if ( ! NEEDSESCAPE( *s ) ) {
+ --d; /* eliminate the \ */
+ }
+ } else if ( SEPARATOR( *s ) ) {
+ while ( SPACE( *(d - 1) ) )
+ d--;
+ if ( value_separator == dn ) { /* 2 or more separators */
+ /* convert to quoted value: */
+ auto char *L = NULL;
+ auto char *R;
+ for ( R = value; (R = strchr( R, '\\' )) && (R < d); L = ++R ) {
+ if ( SEPARATOR( R[1] )) {
+ if ( L == NULL ) {
+ auto const size_t len = R - value;
+ if ( len > 0 ) memmove( value+1, value, len );
+ *value = '"'; /* opening quote */
+ value = R + 1;
+ } else {
+ auto const size_t len = R - L;
+ if ( len > 0 ) {
+ memmove( value, L, len );
+ value += len;
+ }
+ --d;
+ }
+ }
+ }
+ memmove( value, L, d - L + 1 );
+ *d++ = '"'; /* closing quote */
+ }
+ state = B4TYPE;
+ *d++ = (*s == '+') ? '+' : ',';
+ break;
+ }
+ *d++ = *s;
+ break;
+ case INQUOTEDVALUE:
+ if ( gotesc ) {
+ if ( ! NEEDSESCAPE( *s ) ) {
+ --d; /* eliminate the \ */
+ }
+ } else if ( *s == '"' ) {
+ state = B4SEPARATOR;
+ if ( value_separator == dn /* 2 or more separators */
+ || SPACE( value[1] ) || SPACE( d[-1] ) ) {
+ *d++ = *s;
+ } else {
+ /* convert to non-quoted value: */
+ if ( value_separator == NULL ) { /* no separators */
+ memmove ( value, value+1, (d-value)-1 );
+ --d;
+ } else { /* 1 separator */
+ memmove ( value, value+1, (value_separator-value)-1 );
+ *(value_separator - 1) = '\\';
+ }
+ }
+ break;
+ }
+ if ( SEPARATOR( *s )) {
+ if ( value_separator ) value_separator = dn;
+ else value_separator = d;
+ }
+ *d++ = *s;
+ break;
+ case B4SEPARATOR:
+ if ( SEPARATOR( *s ) ) {
+ state = B4TYPE;
+ *d++ = (*s == '+') ? '+' : ',';
+ }
+ break;
+ default:
+/* LDAPDebug( LDAP_DEBUG_ANY,
+ "slapi_dn_normalize - unknown state %d\n", state, 0, 0 );*/
+ break;
+ }
+ if ( *s != '\\' ) {
+ gotesc = 0;
+ } else {
+ gotesc = 1;
+ if ( s+2 < end ) {
+ auto int n = hexchar2int( s[1] );
+ if ( n >= 0 ) {
+ auto int n2 = hexchar2int( s[2] );
+ if ( n2 >= 0 ) {
+ n = (n << 4) + n2;
+ if (n == 0) { /* don't change \00 */
+ *d++ = *++s;
+ *d++ = *++s;
+ gotesc = 0;
+ } else { /* change \xx to a single char */
+ ++s;
+ *(unsigned char*)(s+1) = n;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Trim trailing spaces */
+ while ( d != dn && *(d - 1) == ' ' ) d--;
+
+ *d = 0;
+
+ return( dn );
+}
+
+/* if dn contains an unescaped quote return true */
+DS_EXPORT_SYMBOL int
+ds_dn_uses_LDAPv2_quoting(const char *dn)
+{
+ const char ESC = '\\';
+ const char Q = '"';
+ int ret = 0;
+ const char *p = 0;
+
+ /* check dn for a even number (incl. 0) of ESC followed by Q */
+ if (!dn)
+ return ret;
+
+ p = strchr(dn, Q);
+ if (p)
+ {
+ int nESC = 0;
+ for (--p; (p >= dn) && (*p == ESC); --p)
+ ++nESC;
+ if (!(nESC % 2))
+ ret = 1;
+ }
+
+ return ret;
+}
diff --git a/ldap/admin/lib/dsalib_filename.c b/ldap/admin/lib/dsalib_filename.c
new file mode 100644
index 00000000..e7ecfb12
--- /dev/null
+++ b/ldap/admin/lib/dsalib_filename.c
@@ -0,0 +1,95 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+#include "dsalib.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+static char *
+get_month_str(int month)
+{
+ static char *month_str[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
+ "Nov", "Dec"};
+
+ if ( (month < 1) || (month > 12) )
+ return("Unknown month");
+ return(month_str[month - 1]);
+}
+
+/*
+ * Returns a string describing the meaning of the filename.
+ * Two different formats are supported.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_file_meaning(char *file)
+{
+ static char meaning[BIG_LINE];
+#define FILE_EXPECTED_SIZE1 14
+#define FILE_EXPECTED_SIZE2 17
+ char *name;
+ char *tmp;
+ int i;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int sec;
+ int year;
+
+ /*
+ * Expect a file name in format 06041996123401 (FILE_EXPECTED_SIZE1)
+ * which should return "Jun 4 12:34:01 1996"
+ * OR 1996_06_04_123401
+ * which should return "Jun 4 12:34:01 1996"
+ */
+
+ if ( file == NULL )
+ return(NULL);
+ name = malloc(strlen(file) + 1);
+ if ( name == NULL )
+ return(NULL);
+ strcpy(name, file);
+ if ( (tmp = strrchr(name, '.')) != NULL )
+ *tmp = '\0';
+ if ( strlen(name) == FILE_EXPECTED_SIZE1 ) {
+ for ( i = 0; i < FILE_EXPECTED_SIZE1; i++ )
+ if ( !isdigit(name[i]) )
+ return(NULL);
+ if ( (sscanf(name, "%2d%2d%4d%2d%2d%2d", &month, &day, &year, &hour,
+ &minute, &sec)) == -1 )
+ return(NULL);
+ } else if ( strlen(name) == FILE_EXPECTED_SIZE2 ) {
+ for ( i = 0; i < FILE_EXPECTED_SIZE2; i++ )
+ if ( !isdigit(name[i]) )
+ if ( name[i] != '_' )
+ return(NULL);
+ if ( (sscanf(name, "%4d_%2d_%2d_%2d%2d%2d", &year, &month, &day, &hour,
+ &minute, &sec)) == -1 )
+ return(NULL);
+ } else
+ return(NULL);
+
+ if ( (month < 1) || (month > 12) )
+ return(NULL);
+ if ( (day < 1) || (day > 31) )
+ return(NULL);
+ if ( (year < 1000) || (year > 2100) )
+ return(NULL);
+ if ( (hour < 0) || (hour > 24) )
+ return(NULL);
+ if ( (minute < 0) || (minute > 60) )
+ return(NULL);
+ if ( (sec < 0) || (sec > 60) )
+ return(NULL);
+ sprintf(meaning, "%s % 2d %02d:%02d:%02d %4d", get_month_str(month),
+ day, hour, minute, sec, year);
+ return(meaning);
+}
diff --git a/ldap/admin/lib/dsalib_html.c b/ldap/admin/lib/dsalib_html.c
new file mode 100644
index 00000000..cffae406
--- /dev/null
+++ b/ldap/admin/lib/dsalib_html.c
@@ -0,0 +1,201 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+
+#include "dsalib.h"
+#include "prprf.h"
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* holds the contents of the POSTed data from stdin as an array
+of key/value pairs parsed from the key=value input */
+static char **input = 0;
+
+/* This variable is true if the program should assume stdout is connected
+ to an HTML context e.g. if this is being run as a normal CGI. It is
+ false to indicate that output should not contain HTML formatting,
+ Javascript, etc. put plain ol' ASCII only
+*/
+static int formattedOutput = 1;
+
+/* This is the separator string to use when outputting key/value pairs
+ to be read by the non-HTML front end (Java console)
+*/
+static const char *SEPARATOR = ":"; /* from AdmTask.java */
+
+DS_EXPORT_SYMBOL int
+ds_get_formatted_output(void)
+{
+ return formattedOutput;
+}
+
+DS_EXPORT_SYMBOL void
+ds_set_formatted_output(int val)
+{
+ formattedOutput = val;
+}
+
+DS_EXPORT_SYMBOL void
+ds_print_file_name(char *fileptr)
+{
+ char *meaning;
+
+ fprintf(stdout, "%s", fileptr);
+ if ( (meaning = ds_get_file_meaning(fileptr)) != NULL ) {
+ fprintf(stdout, " (%s)", meaning);
+ }
+}
+
+/*
+ * Get a CGI variable.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_cgi_var(char *cgi_var_name)
+{
+ char *cgi_var_value;
+
+ cgi_var_value = (char *) ds_a_get_cgi_var(cgi_var_name, NULL, NULL);
+ if ( cgi_var_value == NULL ) {
+ /*
+ * The ds_a_get_cgi_var() lies! It gives a NULL even if the
+ * value is "". So assume the variable is there and
+ * return an empty string.
+ */
+ return("");
+ }
+ return(cgi_var_value);
+}
+
+/* parse POST input to a CGI program */
+DS_EXPORT_SYMBOL int
+ds_post_begin(FILE *in)
+{
+ char *vars = NULL, *tmp = NULL, *decoded_vars = NULL;
+ int cl;
+
+ if(!(tmp = getenv("CONTENT_LENGTH")))
+ {
+ ds_report_error(DS_INCORRECT_USAGE, "Browser Error", "Your browser"
+ " sent no content length with a POST command."
+ " Please be sure to use a fully compliant browser.");
+ return 1;
+ }
+
+ cl = atoi(tmp);
+
+ vars = (char *)malloc(cl+1);
+
+ if( !(fread(vars, 1, cl, in)) )
+ {
+ ds_report_error(DS_SYSTEM_ERROR, "CGI error",
+ "The POST variables could not be read from stdin.");
+ return 1;
+ }
+
+ vars[cl] = '\0';
+
+ decoded_vars = ds_URL_decode(vars);
+ free(vars);
+
+ input = ds_string_to_vec(decoded_vars);
+ free(decoded_vars);
+/*
+ for (cl = 0; input[cl]; ++cl)
+ printf("ds_post_begin: read cgi var=[%s]\n", input[cl]);
+*/
+ return 0;
+}
+
+/* parse GET input to a CGI program */
+DS_EXPORT_SYMBOL void
+ds_get_begin(char *query_string)
+{
+ char *decoded_input = ds_URL_decode(query_string);
+ input = ds_string_to_vec(decoded_input);
+ free(decoded_input);
+}
+
+/*
+ Borrowed from libadmin/form_post.c
+*/
+DS_EXPORT_SYMBOL char *
+ds_a_get_cgi_var(char *varname, char *elem_id, char *bongmsg)
+{
+ register int x = 0;
+ int len = strlen(varname);
+ char *ans = NULL;
+
+ while(input[x]) {
+ /* We want to get rid of the =, so len, len+1 */
+ if((!strncmp(input[x], varname, len)) && (*(input[x]+len) == '=')) {
+ ans = strdup(input[x] + len + 1);
+ if(!strcmp(ans, ""))
+ ans = NULL;
+ break;
+ } else
+ x++;
+ }
+ if(ans == NULL) {
+ if ((bongmsg) && strlen(bongmsg))
+ {
+ /* prefix error with varname so output interpreters can determine */
+ /* which parameter is in error */
+ char *msg;
+ if (!ds_get_formatted_output() && (varname != NULL))
+ {
+ msg = PR_smprintf("%s.error: %s %s", varname, elem_id, bongmsg);
+ }
+ else
+ {
+ msg = PR_smprintf("error: %s %s", elem_id, bongmsg);
+ }
+ ds_show_message(msg);
+ PR_smprintf_free(msg);
+ }
+ else
+ return NULL;
+ }
+ else
+ return(ans);
+ /* shut up gcc */
+ return NULL;
+}
+
+DS_EXPORT_SYMBOL char **
+ds_string_to_vec(char *in)
+{
+ char **ans;
+ int vars = 0;
+ register int x = 0;
+ char *tmp;
+
+ in = strdup(in);
+
+ while(in[x])
+ if(in[x++]=='=')
+ vars++;
+
+
+ ans = (char **)calloc(vars+1, sizeof(char *));
+
+ x=0;
+ /* strtok() is not MT safe, but it is okay to call here because it is used in monothreaded env */
+ tmp = strtok(in, "&");
+ ans[x++]=strdup(tmp);
+
+ while((tmp = strtok(NULL, "&"))) {
+ ans[x++] = strdup(tmp);
+ }
+
+ free(in);
+
+ return(ans);
+}
diff --git a/ldap/admin/lib/dsalib_ldif.c b/ldap/admin/lib/dsalib_ldif.c
new file mode 100644
index 00000000..94c0d77f
--- /dev/null
+++ b/ldap/admin/lib/dsalib_ldif.c
@@ -0,0 +1,374 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#include <process.h>
+#include <malloc.h>
+#define popen _popen
+#define pclose _pclose
+#else
+#include <unistd.h>
+#endif
+#include "dsalib.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef XP_WIN32
+#define SCRIPT_SUFFIX "" /* shell scripts have no suffix */
+#else
+#define SCRIPT_SUFFIX ".bat" /* batch file suffix */
+#endif
+
+
+static int
+process_and_report( char *line, int line_size, FILE *cmd )
+{
+ int err = 0;
+ while(fgets(line, line_size, cmd)) {
+ /* Strip off line feeds */
+ int ind = strlen( line ) - 1;
+#ifdef DEBUG_CGI
+ fprintf(stderr, "read line=[%s] ind=%d\n", line, ind);
+#endif /* DEBUG_CGI */
+ fprintf( stdout, ": %s", line );
+ fflush(0);
+ while ( (ind >= 0) &&
+ ((line[ind] == '\n') ||
+ (line[ind] == '\r')) ) {
+ line[ind] = 0;
+ ind--;
+ }
+ if ( ind < 1 ) {
+ continue;
+ }
+ ds_send_status(line);
+ if ( (strstr(line, "bad LDIF") != NULL) ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "invalid ldif file\n");
+#endif /* DEBUG_CGI */
+ err = DS_INVALID_LDIF_FILE;
+ } else if ( 0 == err ) {
+ if ( (strstr(line, "err=") != NULL) ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "unknown error\n");
+#endif /* DEBUG_CGI */
+ err = DS_UNKNOWN_ERROR;
+ }
+ }
+ }
+#ifdef DEBUG_CGI
+ fprintf(stderr, "process_and_report finished err=%d\n", err);
+#endif /* DEBUG_CGI */
+ return err;
+}
+
+static int exec_and_report( char *startup_line )
+{
+ FILE *cmd = NULL;
+ char line[BIG_LINE];
+ int haderror = 0;
+
+ PATH_FOR_PLATFORM( startup_line );
+ alter_startup_line(startup_line);
+
+ fflush(stdout);
+ cmd = popen(startup_line, "r");
+ if(!cmd) {
+ printf("could not open pipe [%s]: %d\n",
+ startup_line, errno);
+#ifdef DEBUG_CGI
+ fprintf(stderr, "could not open pipe [%s]: %d\n",
+ startup_line, errno);
+#endif /* DEBUG_CGI */
+ return DS_CANNOT_EXEC;
+ }
+ haderror = process_and_report( line, sizeof(line), cmd );
+ pclose(cmd);
+
+ return haderror;
+}
+
+/*
+ * Execute a shell command.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_exec_and_report( char *startup_line )
+{
+ return exec_and_report( startup_line );
+}
+
+/*
+ * Create a database based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+static int
+importldif(char *file, int preserve, char *backend, char *subtree)
+{
+ char startup_line[BIG_LINE];
+ char *root;
+ int haderror = 0;
+ int i = 0, error = -1;
+ int status;
+ struct stat fstats;
+ char errbuf[ BIG_LINE ];
+ char **db_files = NULL, *changelogdir = NULL;
+ int rc;
+
+ errbuf[ 0 ] = '\0';
+
+ if ( file == NULL ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: null file\n");
+#endif /* DEBUG_CGI */
+ return DS_NULL_PARAMETER;
+ }
+ status = ds_get_updown_status();
+ if ( status == DS_SERVER_UP ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: server is not down\n");
+#endif /* DEBUG_CGI */
+ return DS_SERVER_MUST_BE_DOWN;
+ }
+ if ( (root = ds_get_install_root()) == NULL ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: could not get server root\n");
+#endif /* DEBUG_CGI */
+ return DS_NO_SERVER_ROOT;
+ }
+
+ if ( file[strlen(file) - 1] == '\n' ) /* strip out returns */
+ file[strlen(file) - 1] = '\0';
+
+ /* Make sure the file exists and is not a directory: 34347 */
+ if( stat( file, &fstats ) == -1 && errno == ENOENT ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: could not open %s\n", file);
+#endif /* DEBUG_CGI */
+ return DS_CANNOT_OPEN_LDIF_FILE;
+ } else if( fstats.st_mode & S_IFDIR ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: not a file %s\n", file);
+#endif /* DEBUG_CGI */
+ return DS_IS_A_DIRECTORY;
+ }
+
+ if ( preserve ) {
+ sprintf(startup_line, "%s%cldif2db%s -i %s%s%s",
+ root, FILE_SEP, SCRIPT_SUFFIX,
+ ENQUOTE, file, ENQUOTE);
+ } else if (backend) {
+ sprintf(startup_line, "%s%cldif2db%s -n %s%s%s -i %s%s%s",
+ root, FILE_SEP, SCRIPT_SUFFIX,
+ ENQUOTE, backend, ENQUOTE,
+ ENQUOTE, file, ENQUOTE);
+ } else if (subtree) {
+ sprintf(startup_line, "%s%cldif2db%s -s %s%s%s -i %s%s%s",
+ root, FILE_SEP, SCRIPT_SUFFIX,
+ ENQUOTE, subtree, ENQUOTE,
+ ENQUOTE, file, ENQUOTE);
+ } else {
+ sprintf(startup_line, "%s%cldif2db%s -i %s%s%s -noconfig",
+ root, FILE_SEP, SCRIPT_SUFFIX,
+ ENQUOTE, file, ENQUOTE);
+ }
+ alter_startup_line(startup_line);
+ fflush(stdout);
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: executing %s\n", startup_line);
+#endif /* DEBUG_CGI */
+ error = exec_and_report(startup_line);
+ /*error = system(startup_line);*/
+ if ( error != 0 ) {
+#ifdef DEBUG_CGI
+ fprintf(stderr, "importldif: error=%d\n", error);
+#endif /* DEBUG_CGI */
+ return error;
+ }
+
+ /* Remove the changelog database, if present */
+ changelogdir = ds_get_config_value(0xdeadbeef);
+ if ( changelogdir != NULL ) {
+ db_files = ds_get_file_list( changelogdir );
+ if ( db_files != NULL ) {
+ ds_send_status("Removing changelog database...");
+ }
+ for ( i = 0; db_files != NULL && db_files[ i ] != NULL; i++ ) {
+ char sbuf[ BIG_LINE ];
+ char filename[ BIG_LINE ];
+ if ( strlen( db_files[ i ]) > 0 ) {
+ sprintf( filename, "%s%c%s", changelogdir,
+ FILE_SEP, db_files[ i ]);
+ sprintf(sbuf, "Removing %s", filename);
+ ds_send_status( sbuf );
+ rc = unlink( filename);
+ if ( rc != 0 ) {
+ sprintf( errbuf, "Warning: some files in %s could not "
+ "be removed\n", changelogdir );
+ haderror++;
+ }
+ }
+ }
+ }
+ if ( strlen( errbuf ) > 0 ) {
+ ds_send_error( errbuf, 0 );
+ }
+
+ return error;
+}
+
+/*
+ * Create a database based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_ldif2db(char *file)
+{
+ return importldif( file, 0, NULL, NULL );
+}
+
+/*
+ * Create a database based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_ldif2db_preserve(char *file)
+{
+ return importldif( file, 1, NULL, NULL );
+}
+
+/*
+ * import an ldif file into a named backend or subtree
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_ldif2db_backend_subtree(char *file, char *backend, char *subtree)
+{
+ return importldif( file, 0, backend, subtree );
+}
+
+/*
+ * Create a LDIF file based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_db2ldif_subtree(char *file, char *subtree)
+{
+ char startup_line[BIG_LINE];
+ char statfile[PATH_MAX];
+ char outfile[PATH_MAX];
+ char scriptfile[PATH_MAX];
+ char *tmp_dir;
+ char *root;
+ int haderror = 0;
+ int error = -1;
+ FILE *sf = NULL;
+
+ if ( (root = ds_get_install_root()) == NULL ) {
+ return DS_NO_SERVER_ROOT;
+ }
+
+ if ( (file == NULL) || (strlen(file) == 0) )
+ file = NULL;
+
+ tmp_dir = ds_get_tmp_dir();
+ sprintf(statfile, "%s%cdb2ldif.%d", tmp_dir, FILE_SEP, (int) getpid());
+
+#if defined( XP_WIN32 )
+ if( file == NULL )
+ {
+ time_t ltime;
+ file = malloc( BIG_LINE );
+
+ time( &ltime );
+ sprintf( file, "%s", ctime( &ltime ) );
+ ds_timetofname( file );
+ }
+#endif
+
+ if ( file == NULL )
+ *outfile = 0;
+ else
+ strcpy( outfile, file );
+
+ sprintf(scriptfile, "%s%cdb2ldif", root, FILE_SEP);
+
+ PATH_FOR_PLATFORM( outfile );
+ PATH_FOR_PLATFORM( scriptfile );
+
+ if ( subtree == NULL ) {
+ sprintf(startup_line,
+ "%s "
+ "%s%s%s > "
+ "%s%s%s 2>&1",
+ scriptfile,
+ ENQUOTE, outfile, ENQUOTE,
+ ENQUOTE, statfile, ENQUOTE);
+ } else {
+ sprintf(startup_line,
+ "%s "
+ "%s%s%s "
+ "-s \"%s\" > "
+ "%s%s%s 2>&1",
+ scriptfile,
+ ENQUOTE, outfile, ENQUOTE,
+ subtree,
+ ENQUOTE, statfile, ENQUOTE);
+ }
+
+ fflush(0);
+ alter_startup_line(startup_line);
+ error = system(startup_line);
+ if ( error == -1 ) {
+ return DS_CANNOT_EXEC;
+ }
+ sf = fopen(statfile, "r");
+ if( sf ) {
+ while ( fgets(startup_line, BIG_LINE, sf) ) {
+ /*
+ The db2ldif process will usually print out a summary at the
+ end, but that is not an error
+ */
+ char *ptr = strstr(startup_line, "Processed");
+ if (ptr && strstr(ptr, "entries."))
+ {
+ ds_show_message(startup_line);
+ }
+ else
+ {
+ haderror = 1;
+ ds_send_error(startup_line, 0);
+ }
+ }
+ fclose(sf);
+ unlink(statfile);
+ }
+
+ if ( haderror )
+ return DS_UNKNOWN_ERROR;
+ return 0;
+}
+
+/*
+ * Create a LDIF file based on a file name.
+ * 0: success
+ * anything else: failure
+ */
+DS_EXPORT_SYMBOL int
+ds_db2ldif(char *file)
+{
+ return ds_db2ldif_subtree(file, NULL);
+}
diff --git a/ldap/admin/lib/dsalib_location.c b/ldap/admin/lib/dsalib_location.c
new file mode 100644
index 00000000..06cbafb5
--- /dev/null
+++ b/ldap/admin/lib/dsalib_location.c
@@ -0,0 +1,142 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+#include "dsalib.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * Returns the server root. Info is
+ * returned in a static area. The caller must copy it
+ * for reuse if needed.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_server_root()
+{
+ char *root;
+
+ if ( (root = getenv("NETSITE_ROOT")) == NULL )
+ return(NULL);
+
+ /* WIN32: Needed to take care of embedded space, */
+ /* otherwise system() call fails */
+ root = ds_makeshort( root );
+
+ return root;
+}
+
+/*
+ * Returns the install location of the server. Info is
+ * returned in a static area. The caller must copy it
+ * for reuse if needed.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_install_root()
+{
+ char *root;
+ char *ds_name;
+ static char install_root[PATH_MAX];
+
+ if ( (root = ds_get_server_root()) == NULL )
+ return(NULL);
+ if ( (ds_name = ds_get_server_name()) == NULL )
+ return(NULL);
+
+ sprintf(install_root, "%s/%s", root, ds_name);
+ return(install_root);
+}
+
+/*
+ * Returns the install location of the server under the admserv
+ * directory.
+ */
+DS_EXPORT_SYMBOL char *
+ds_get_admserv_based_root()
+{
+ char *root;
+ char *ds_name;
+ static char install_root[PATH_MAX];
+
+ if ( (root = getenv("ADMSERV_ROOT")) == NULL )
+ return(NULL);
+ if ( (ds_name = ds_get_server_name()) == NULL )
+ return(NULL);
+ sprintf(install_root, "%s/%s", root, ds_name);
+ return(install_root);
+}
+
+DS_EXPORT_SYMBOL char *
+ds_get_server_name()
+{
+ if( getenv("SERVER_NAMES") )
+ return( getenv("SERVER_NAMES") );
+ else {
+ static char logfile[PATH_MAX];
+ char *buf;
+ char *out = logfile;
+ buf = getenv("SCRIPT_NAME");
+ if ( buf && (*buf == '/') )
+ buf++;
+ while ( *buf && (*buf != '/') ) {
+ *out++ = *buf++;
+ }
+ *out = 0;
+ return logfile;
+ }
+}
+
+DS_EXPORT_SYMBOL char *
+ds_get_logfile_name(int config_type)
+{
+ char *filename;
+ char **ds_config = NULL;
+ static char logfile[PATH_MAX];
+
+ if ( (ds_config = ds_get_config(DS_REAL_CONFIG)) == NULL ) {
+ /* For DS 4.0, no error output if file doesn't exist - that's
+ a normal situation */
+ /* ds_send_error("ds_get_config(DS_REAL_CONFIG) == NULL", 0); */
+ return(NULL);
+ }
+ filename = ds_get_value(ds_config, ds_get_var_name(config_type), 0, 1);
+
+ if ( filename == NULL ) {
+ /* For DS 4.0, no error output if file doesn't exist - that's
+ a normal situation */
+ /* ds_send_error("ds_get_logfile_name: filename == NULL", 0); */
+ return(NULL);
+ }
+ if ( ((int) strlen(filename)) >= PATH_MAX ) {
+ ds_send_error("ds_get_logfile_name: filename too long", 0);
+ free(filename);
+ return(NULL);
+ }
+ strcpy(logfile, filename);
+ free(filename);
+ return(logfile);
+}
+
+DS_EXPORT_SYMBOL char *
+ds_get_errors_name()
+{
+ return( ds_get_logfile_name(DS_ERRORLOG) );
+}
+
+DS_EXPORT_SYMBOL char *
+ds_get_access_name()
+{
+ return( ds_get_logfile_name(DS_ACCESSLOG) );
+}
+
+DS_EXPORT_SYMBOL char *
+ds_get_audit_name()
+{
+ return( ds_get_logfile_name(DS_AUDITFILE) );
+}
+
diff --git a/ldap/admin/lib/dsalib_pw.c b/ldap/admin/lib/dsalib_pw.c
new file mode 100644
index 00000000..21fd8ecb
--- /dev/null
+++ b/ldap/admin/lib/dsalib_pw.c
@@ -0,0 +1,29 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * Adjust password policy management related variables.
+ *
+ * Valerie Chu
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "ldap.h"
+#include "ldif.h"
+#include "sechash.h"
+#include "dsalib.h"
+#include "dsalib_pw.h"
+
+extern char * salted_sha1_pw_enc(char *);
+
+DS_EXPORT_SYMBOL char *
+ds_salted_sha1_pw_enc (char* pwd)
+{
+ return( salted_sha1_pw_enc(pwd) );
+}
diff --git a/ldap/admin/lib/dsalib_tailf.c b/ldap/admin/lib/dsalib_tailf.c
new file mode 100644
index 00000000..04e04578
--- /dev/null
+++ b/ldap/admin/lib/dsalib_tailf.c
@@ -0,0 +1,206 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "dsalib.h"
+#include "prthread.h"
+
+/*
+ * Function: adjustFile
+ * Property: Adjust the file offset to the "tail" of the file
+ * Called by: DisplayTail
+ * Return: -1 for error, else file size
+ */
+static int
+adjustFile(FILE *fp, int curSize)
+{
+ struct stat statBuf;
+ int fd = fileno(fp);
+
+ if ( fstat(fd, &statBuf) == -1 )
+ return(-1);
+ if ( statBuf.st_size < curSize ) /* file has shrunk! */
+ {
+ if ( fseek(fp, 0L, 0) == -1 ) /* get back to the beginning */
+ return(-1);
+ }
+ curSize = (int) statBuf.st_size;
+ if ( !curSize )
+ curSize = 1;
+ return(curSize);
+}
+
+/*
+ * Function: wrapLines
+ * Property: wrap lines at 50 characters. When a wrap point is encountered,
+ * insert the string "\n", since the buffer is going to be placed
+ * inside a JavaScript alert() call.
+ * Called by: ds_display_tail
+ * Return: pointer to wrapped buffer. Caller should free.
+ */
+static char *
+wrapLines( char *buf )
+{
+ char *src = buf;
+ char *obuf, *dst;
+ int lwidth = 0;
+
+ obuf = malloc( strlen( buf ) * 2 ); /* conservative */
+ if ( obuf == NULL ) {
+ return NULL;
+ }
+ dst = obuf;
+ while ( *src != '\0' ) {
+ if (( ++lwidth > 50 ) && isspace( *src )) {
+ *dst++ = '\\';
+ *dst++ = 'n';
+ lwidth = 0;
+ src++;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = '\0';
+ return obuf;
+}
+
+DS_EXPORT_SYMBOL int
+ds_get_file_size(char *fileName)
+{
+ struct stat statBuf;
+
+ if ( fileName == NULL )
+ return(0);
+
+ if ( stat(fileName, &statBuf) == -1 )
+ return(0);
+
+ return(statBuf.st_size);
+}
+
+/*
+ * Function: ds_display_tail
+ * Property: follow the tail and display it for timeOut secs or until the line
+ * read from the file contains the string doneMsg; the lastLine, if not null,
+ * will be filled in with the last line read from the file; this is useful
+ * for determining why the server failed to start e.g. port in use, ran out
+ * of semaphores, database is corrupted, etc.
+ * Calls: adjustFile
+ */
+DS_EXPORT_SYMBOL void
+ds_display_tail(char *fileName, int timeOut, int startSeek, char *doneMsg,
+ char *lastLine)
+{
+ FILE *fp = NULL;
+ int fd;
+ char msgBuf[BIG_LINE];
+ struct stat statBuf;
+ int curSize;
+ int i = timeOut;
+
+ if (lastLine != NULL)
+ lastLine[0] = 0;
+
+ if ( fileName == NULL )
+ return;
+ /*
+ * Open the file.
+ * Try to keep reading it assuming that it may get truncated.
+ */
+ while (i && !fp)
+ {
+ fp = fopen(fileName, "r");
+ if (!fp)
+ {
+ PR_Sleep(PR_SecondsToInterval(1));
+ --i;
+ /* need to print something so http connection doesn't
+ timeout and also to let the user know something is
+ happening . . .
+ */
+ if (!(i % 10))
+ {
+ ds_send_status("Attempting to obtain server status . . .");
+ }
+ }
+ }
+
+ if (!i || !fp)
+ return;
+
+ fd = fileno(fp);
+ if ( fstat(fd, &statBuf) == -1 ) {
+ (void) fclose(fp);
+ return;
+ }
+ curSize = (int) statBuf.st_size;
+ if ( startSeek < curSize )
+ curSize = startSeek;
+ if ( curSize > 0 )
+ if ( fseek(fp, curSize, SEEK_SET) == -1 ) {
+ (void) fclose(fp);
+ return;
+ }
+ if ( !curSize )
+ curSize = 1; /* ensure minimum */
+
+ while ( i )
+ {
+ int newCurSize;
+
+ newCurSize = curSize = adjustFile(fp, curSize);
+ if ( curSize == -1 ) {
+ (void) fclose(fp);
+ return;
+ }
+ while ( fgets(msgBuf, sizeof(msgBuf), fp) )
+ {
+ char *tmp;
+ if (lastLine != NULL)
+ strcpy(lastLine, msgBuf);
+ if ( (tmp = strchr(msgBuf, ((int) '\n'))) != NULL )
+ *tmp = '\0'; /* strip out real newlines from here */
+ ds_send_status(msgBuf);
+ if ( (strstr(msgBuf, "WARNING: ") != NULL) ||
+ (strstr(msgBuf, "ERROR: ") != NULL) ) {
+ char *wrapBuf;
+
+ wrapBuf = wrapLines( msgBuf );
+ if ( wrapBuf != NULL ) {
+ ds_send_error(wrapBuf, 5);
+ } else {
+ ds_send_error(msgBuf, 5);
+ }
+ }
+ if ( (doneMsg != NULL) && (strstr(msgBuf, doneMsg)) ) {
+ (void) fclose(fp);
+ return;
+ }
+ newCurSize = adjustFile(fp, newCurSize);
+ if ( newCurSize == -1 ) {
+ (void) fclose(fp);
+ return;
+ }
+ }
+ if ( ferror(fp) ) {
+ (void) fclose(fp);
+ return;
+ }
+ clearerr(fp); /* clear eof condition */
+ PR_Sleep(PR_SecondsToInterval(1));
+ if ( newCurSize != curSize )
+ i = timeOut; /* keep going till no more changes */
+ else
+ i--;
+ }
+ (void) fclose(fp);
+}
diff --git a/ldap/admin/lib/dsalib_updown.c b/ldap/admin/lib/dsalib_updown.c
new file mode 100644
index 00000000..4f041208
--- /dev/null
+++ b/ldap/admin/lib/dsalib_updown.c
@@ -0,0 +1,702 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#include <process.h>
+#include "regparms.h"
+#else
+#include <signal.h>
+#include <sys/signal.h>
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "dsalib.h"
+#include <string.h>
+#include "nspr.h"
+
+#if defined( XP_WIN32 )
+SC_HANDLE schService;
+SC_HANDLE schSCManager;
+
+int StartServer();
+int StopandRestartServer();
+int StopServer();
+
+int StopNetscapeProgram();
+int StartNetscapeProgram();
+
+int StopNetscapeService();
+int StartNetscapeService();
+void WaitForServertoStop();
+#endif
+
+/*
+ * Get status for the Directory Server.
+ * 0 -- down
+ * 1 -- up
+ * -1 -- unknown
+ */
+#if !defined( XP_WIN32 )
+static pid_t server_pid;
+
+DS_EXPORT_SYMBOL int
+ds_get_updown_status()
+{
+ char pid_file_name[BIG_LINE];
+ char *root;
+ FILE *pidfile;
+ int ipid = -1;
+ int status = 0;
+
+ if ( (root = ds_get_install_root()) == NULL ) {
+ fprintf(stderr, "ds_get_updown_status: could not get install root\n");
+ return(DS_SERVER_UNKNOWN);
+ }
+ sprintf(pid_file_name, "%s/logs/pid", root);
+ pidfile = fopen(pid_file_name, "r");
+ if ( pidfile == NULL ) {
+/*
+ fprintf(stderr,
+ "ds_get_updown_status: could not open pid file=%s errno=%d\n",
+ pid_file_name, errno);
+*/
+ return(DS_SERVER_DOWN);
+ }
+ status = fscanf(pidfile, "%d\n", &ipid);
+ fclose(pidfile);
+ if ( status == -1 ) {
+ fprintf(stderr,
+ "ds_get_updown_status: pidfile=%s server_pid=%d errno=%d\n",
+ pid_file_name, ipid, errno);
+ unlink(pid_file_name); /* junk in file? */
+ return(DS_SERVER_DOWN);
+ }
+ server_pid = (pid_t) ipid;
+ if ( (status = kill(server_pid, 0)) != 0 && errno != EPERM ) {
+ /* we should get ESRCH if the server is down, anything else may be
+ a real problem */
+ if (errno != ESRCH) {
+ fprintf(stderr,
+ "ds_get_updown_status: pidfile=%s server_pid=%d status=%d errno=%d\n",
+ pid_file_name, server_pid, status, errno);
+ }
+ unlink(pid_file_name); /* pid does not exist! */
+ return(DS_SERVER_DOWN);
+ }
+ return(DS_SERVER_UP);
+}
+#else
+DS_EXPORT_SYMBOL int
+ds_get_updown_status()
+{
+ char *ds_name = ds_get_server_name();
+ HANDLE hServerDoneEvent = NULL;
+
+ /* watchdog.c creates a global event of this same name */
+ if((hServerDoneEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, ds_name)) != NULL)
+ {
+ CloseHandle(hServerDoneEvent);
+ return(DS_SERVER_UP);
+ }
+ if(GetLastError() == ERROR_ACCESS_DENIED) /* it exists */
+ return(DS_SERVER_UP);
+
+ /* assume it's not running. */
+ return(DS_SERVER_DOWN);
+}
+#endif
+
+/*
+ This function does not require calling ds_get_config(), but requires
+ that that information be passed in. This is very useful for starting
+ the server during installation, because we already have all of the
+ configuration information in memory, we don't need to read it in
+*/
+DS_EXPORT_SYMBOL int
+ds_bring_up_server_install(int verbose, char *root, char *errorlog)
+{
+#if !defined( XP_WIN32 )
+ char startup_line[BIG_LINE];
+ char statfile[PATH_MAX];
+ char *tmp_dir;
+#endif
+ int error = -1;
+ int status = DS_SERVER_DOWN;
+ int cur_size = 0;
+ FILE *sf = NULL;
+ char msgBuf[BIG_LINE] = {0};
+ int secondsToWaitForServer = 600;
+ char *serverStartupString = "slapd started.";
+
+ status = ds_get_updown_status();
+ if ( status == DS_SERVER_UP )
+ return(DS_SERVER_ALREADY_UP);
+ if (!root || !errorlog)
+ return(DS_SERVER_UNKNOWN);
+
+ if (verbose) {
+ ds_send_status("starting up server ...");
+ cur_size = ds_get_file_size(errorlog);
+ }
+
+#if !defined( XP_WIN32 )
+ tmp_dir = ds_get_tmp_dir();
+ sprintf(statfile, "%s%cstartup.%d", tmp_dir, FILE_SEP, (int)getpid());
+
+ sprintf(startup_line, "%s%c%s > %s 2>&1",
+ root, FILE_SEP, START_SCRIPT, statfile);
+ alter_startup_line(startup_line);
+ error = system(startup_line);
+ if (error == -1)
+ error = DS_SERVER_DOWN; /* could not start server */
+ else
+ error = DS_SERVER_UP; /* started server */
+#else
+ error = StartServer();
+#endif
+
+ if (error != DS_SERVER_UP)
+ {
+#if !defined( XP_WIN32 )
+ FILE* fp = fopen(statfile, "r");
+ if (fp)
+ {
+ while(fgets(msgBuf, BIG_LINE, fp))
+ ds_send_status(msgBuf);
+ fclose(fp);
+ }
+#endif
+ return DS_SERVER_COULD_NOT_START;
+ }
+
+ if (verbose)
+ {
+ /*
+ * Stop in N secs or whenever the startup message comes up.
+ * Do whichever happens first. msgBuf will contain the last
+ * line read from the errorlog.
+ */
+ ds_display_tail(errorlog, secondsToWaitForServer, cur_size,
+ serverStartupString, msgBuf);
+ }
+ if ( error != DS_SERVER_UP ) {
+ int retval = DS_SERVER_UNKNOWN;
+ if (strstr(msgBuf, "semget"))
+ retval = DS_SERVER_MAX_SEMAPHORES;
+ else if (strstr(msgBuf, "Back-End Initialization Failed"))
+ retval = DS_SERVER_CORRUPTED_DB;
+ else if (strstr(msgBuf, "not initialized... exiting"))
+ retval = DS_SERVER_CORRUPTED_DB;
+ else if (strstr(msgBuf, "address is in use"))
+ retval = DS_SERVER_PORT_IN_USE;
+#if defined( XP_WIN32 )
+ /* on NT, if we run out of resources, there will not even be an error
+ log
+ */
+ else if (msgBuf[0] == 0) {
+ retval = DS_SERVER_NO_RESOURCES;
+ }
+#endif
+ if (verbose)
+ ds_send_error("error in starting server.", 1);
+ return(retval);
+ }
+ if (verbose) {
+#if !defined( XP_WIN32 )
+ if( !(sf = fopen(statfile, "r")) ) {
+ ds_send_error("could not read status file.", 1);
+ return(DS_SERVER_UNKNOWN);
+ }
+
+ while ( fgets(startup_line, BIG_LINE, sf) )
+ ds_send_error(startup_line, 0);
+ fclose(sf);
+ unlink(statfile);
+#endif
+ status = DS_SERVER_UNKNOWN;
+ if (strstr(msgBuf, "semget"))
+ status = DS_SERVER_MAX_SEMAPHORES;
+ else if (strstr(msgBuf, "Back-End Initialization Failed"))
+ status = DS_SERVER_CORRUPTED_DB;
+ else if (strstr(msgBuf, "not initialized... exiting"))
+ status = DS_SERVER_CORRUPTED_DB;
+ else if (strstr(msgBuf, "address is in use"))
+ status = DS_SERVER_PORT_IN_USE;
+#if defined( XP_WIN32 )
+ /* on NT, if we run out of resources, there will not even be an error
+ log
+ */
+ else if (msgBuf[0] == 0) {
+ status = DS_SERVER_NO_RESOURCES;
+ }
+#endif
+ } else {
+ int tries;
+ for (tries = 0; tries < secondsToWaitForServer; tries++) {
+ if (ds_get_updown_status() == DS_SERVER_UP) break;
+ PR_Sleep(PR_SecondsToInterval(1));
+ }
+ if (verbose) {
+ char str[100];
+ sprintf(str, "Had to retry %d times", tries);
+ ds_send_status(str);
+ }
+ }
+
+ if ( (status == DS_SERVER_DOWN) || (status == DS_SERVER_UNKNOWN) )
+ status = ds_get_updown_status();
+
+ return(status);
+}
+
+/*
+ * Start the Directory Server and return status.
+ * Do not start if the server is already started.
+ * 0 -- down
+ * 1 -- up
+ * -1 -- unknown
+ * -2 -- already up
+ */
+
+DS_EXPORT_SYMBOL int
+ds_bring_up_server(int verbose)
+{
+ char *root;
+ int status;
+ char *errorlog;
+ status = ds_get_updown_status();
+ if ( status == DS_SERVER_UP )
+ return(DS_SERVER_ALREADY_UP);
+ if ( (root = ds_get_install_root()) == NULL )
+ return(DS_SERVER_UNKNOWN);
+
+ errorlog = ds_get_config_value(DS_ERRORLOG);
+ if ( errorlog == NULL ) {
+ errorlog = ds_get_errors_name(); /* fallback */
+ }
+ return ds_bring_up_server_install(verbose, root, errorlog);
+}
+
+DS_EXPORT_SYMBOL int
+ds_bring_down_server()
+{
+ char *root;
+ int status;
+ int cur_size;
+ char *errorlog;
+
+ status = ds_get_updown_status(); /* set server_pid too! */
+ if ( status != DS_SERVER_UP ) {
+ ds_send_error("The server is not up.", 0);
+ return(DS_SERVER_ALREADY_DOWN);
+ }
+ if ( (root = ds_get_install_root()) == NULL ) {
+ ds_send_error("Could not get the server root directory.", 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+
+ ds_send_status("shutting down server ...");
+ if (!(errorlog = ds_get_errors_name())) {
+ ds_send_error("Could not get the error log filename.", 0);
+ return DS_SERVER_UNKNOWN;
+ }
+
+ cur_size = ds_get_file_size(errorlog);
+#if !defined( XP_WIN32 )
+ if ( (kill(server_pid, SIGTERM)) != 0) {
+ if (errno == EPERM) {
+ ds_send_error("Not permitted to kill server.", 0);
+ fprintf (stdout, "[%s]: kill (%li, SIGTERM) failed with errno = EPERM.<br>\n",
+ ds_get_server_name(), (long)server_pid);
+ } else {
+ ds_send_error("error in killing server.", 1);
+ }
+ return(DS_SERVER_UNKNOWN);
+ }
+#else
+ if( StopServer() == DS_SERVER_DOWN )
+ {
+ ds_send_status("shutdown: server shut down");
+ }
+ else
+ {
+ ds_send_error("error in killing server.", 1);
+ return(DS_SERVER_UNKNOWN);
+ }
+#endif
+ /*
+ * Wait up to SERVER_STOP_TIMEOUT seconds for the stopped message to
+ * appear in the error log.
+ */
+ ds_display_tail(errorlog, SERVER_STOP_TIMEOUT, cur_size, "slapd stopped.", NULL);
+ /* in some cases, the server will tell us it's down when it's really not,
+ so give the OS a chance to remove it from the process table */
+ PR_Sleep(PR_SecondsToInterval(1));
+ return(ds_get_updown_status());
+}
+
+#if defined( XP_WIN32 )
+
+static BOOLEAN
+IsService()
+{
+#if 0
+ CHAR ServerKey[512], *ValueString;
+ HKEY hServerKey;
+ DWORD dwType, ValueLength, Result;
+
+ sprintf(ServerKey,"%s\\%s\0", COMPANY_KEY, PRODUCT_KEY);
+
+ Result = RegOpenKey(HKEY_LOCAL_MACHINE, ServerKey, &hServerKey);
+ if (Result != ERROR_SUCCESS) {
+ return TRUE;
+ }
+ ValueLength = 512;
+ ValueString = (PCHAR)malloc(ValueLength);
+
+ Result = RegQueryValueEx(hServerKey, IS_SERVICE_KEY, NULL,
+ &dwType, ValueString, &ValueLength);
+ if (Result != ERROR_SUCCESS) {
+ return TRUE;
+ }
+ if (strcmp(ValueString, "yes")) {
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+#else
+ return TRUE;
+#endif
+}
+
+#if 0
+NSAPI_PUBLIC BOOLEAN
+IsAdminService()
+{
+ CHAR AdminKey[512], *ValueString;
+ HKEY hAdminKey;
+ DWORD dwType, ValueLength, Result;
+
+ sprintf(AdminKey,"%s\\%s\0", COMPANY_KEY, ADMIN_REGISTRY_ROOT_KEY);
+
+ Result = RegOpenKey(HKEY_LOCAL_MACHINE, AdminKey, &hAdminKey);
+ if (Result != ERROR_SUCCESS) {
+ return TRUE;
+ }
+ ValueLength = 512;
+ ValueString = (PCHAR)malloc(ValueLength);
+
+ Result = RegQueryValueEx(hAdminKey, IS_SERVICE_KEY, NULL,
+ &dwType, ValueString, &ValueLength);
+ if (Result != ERROR_SUCCESS) {
+ return TRUE;
+ }
+ if (strcmp(ValueString, "yes")) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+#endif
+
+int
+StartServer()
+{
+ CHAR ErrorString[512];
+ BOOLEAN Service;
+
+ /* Figure out if the server is a service or an exe */
+ Service = IsService();
+
+ if(Service) {
+ if (!(schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ ))) {
+ sprintf(ErrorString,
+ "Error: Could not open the ServiceControlManager:%d "
+ "Please restart the server %s from the Services Program Item "
+ "in the Control Panel", ds_get_server_name(), GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+ return(StartNetscapeService());
+ } else {
+ return(StartNetscapeProgram());
+ }
+}
+
+int
+StopandRestartServer()
+{
+ CHAR ErrorString[512];
+ BOOLEAN Service;
+
+
+ /* First figure out if the server is a service or an exe */
+ Service = IsService();
+ if(Service) {
+ if (!(schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ ))) {
+ sprintf(ErrorString,
+ "Error: Could not restart server."
+ "Please restart the server %s from the Services Program Item "
+ "in the Control Panel", ds_get_server_name());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+ if (StopNetscapeService() != DS_SERVER_DOWN)
+ return(DS_SERVER_UNKNOWN);
+
+ return(StartNetscapeService());
+ } else {
+ if (StopNetscapeProgram() != DS_SERVER_DOWN)
+ return(DS_SERVER_UNKNOWN);
+ return(StartNetscapeProgram());
+ }
+
+}
+
+int
+StopServer()
+{
+ CHAR ErrorString[512];
+ BOOLEAN Service;
+
+ /* First figure out if the server is a service or an exe */
+ Service = IsService();
+
+ if(Service) {
+ if (!(schSCManager = OpenSCManager(
+ NULL, // machine (NULL == local)
+ NULL, // database (NULL == default)
+ SC_MANAGER_ALL_ACCESS // access required
+ ))) {
+ sprintf(ErrorString,
+ "Error: Could not open the ServiceControlManager:%d "
+ "Please restart the server %s from the Services Program Item "
+ "in the Control Panel", ds_get_server_name(), GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+ return(StopNetscapeService());
+ } else {
+ return(StopNetscapeProgram());
+ }
+}
+
+int
+StartNetscapeProgram()
+{
+ char line[BIG_LINE], cmd[BIG_LINE];
+ char *tmp = ds_get_install_root();
+
+ CHAR ErrorString[512];
+ STARTUPINFO siStartInfo;
+ PROCESS_INFORMATION piProcInfo;
+ FILE *CmdFile;
+
+ ZeroMemory(line, BIG_LINE);
+
+ sprintf(line, "%s\\startsrv.bat", tmp);
+
+ CmdFile = fopen(line, "r");
+ if (!CmdFile)
+ {
+ sprintf(ErrorString, "Error:Tried to start Netscape server %s "
+ ": Could not open the startup script %s :Error %d. Please "
+ "run startsrv.bat from the server's root directory.",
+ ds_get_server_name(), line, errno);
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_DOWN);
+ }
+
+ ZeroMemory(cmd, BIG_LINE);
+ if (!fread(cmd, 1, BIG_LINE, CmdFile))
+ {
+ sprintf(ErrorString, "Error:Tried to start Netscape server %s "
+ ": Could not read the startup script %s :Error %d. Please "
+ "run startsrv.bat from the server's root directory.",
+ ds_get_server_name(), line, errno);
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_DOWN);
+ }
+
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.lpReserved = siStartInfo.lpReserved2 = NULL;
+ siStartInfo.cbReserved2 = 0;
+ siStartInfo.lpDesktop = NULL;
+
+ if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE,
+ 0, NULL, NULL, &siStartInfo, &piProcInfo))
+ {
+ sprintf(ErrorString, "Error:Tried to start Netscape server %s "
+ ": Could not start up the startup script %s :Error %d. Please "
+ "run startsrv.bat from the server's root directory.",
+ ds_get_server_name(), line, GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_DOWN);
+ }
+
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ return(DS_SERVER_UP);
+}
+
+int
+StopNetscapeProgram()
+{
+ HANDLE hEvent;
+ CHAR ErrorString[512];
+ char *servid = ds_get_server_name();
+
+ hEvent = CreateEvent(NULL, TRUE, FALSE, servid);
+ if(!SetEvent(hEvent))
+ {
+ sprintf(ErrorString, "Tried to stop existing Netscape server %s"
+ ": Could not signal it to stop :Error %d",
+ servid, GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+
+ return(DS_SERVER_DOWN);
+}
+
+int
+StopNetscapeService()
+{
+ BOOL ret;
+ SERVICE_STATUS ServiceStatus;
+ DWORD Error;
+ CHAR ErrorString[512];
+ char *serviceName = ds_get_server_name();
+
+ schService = OpenService(schSCManager, serviceName, SERVICE_ALL_ACCESS);
+
+ if (schService == NULL)
+ {
+ PR_snprintf(ErrorString, 512, "Tried to open Netscape service"
+ " %s: Error %d (%s). Please"
+ " stop the server from the Services Item in the Control Panel",
+ serviceName, GetLastError(), ds_system_errmsg());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UP);
+ }
+
+ ret = ControlService(schService, SERVICE_CONTROL_STOP, &ServiceStatus);
+ Error = GetLastError();
+ /* if ControlService returns with ERROR_SERVICE_CANNOT_ACCEPT_CTRL and
+ the server status indicates that it is either shutdown or in the process
+ of shutting down, then just wait for it to stop as usual */
+ if (ret ||
+ ((Error == ERROR_SERVICE_CANNOT_ACCEPT_CTRL) &&
+ ((ServiceStatus.dwCurrentState == SERVICE_STOPPED) ||
+ (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING))))
+ {
+ CloseServiceHandle(schService);
+ /* We make sure that the service is stopped */
+ WaitForServertoStop();
+ return(DS_SERVER_DOWN);
+ }
+ else if (Error != ERROR_SERVICE_NOT_ACTIVE)
+ {
+ PR_snprintf(ErrorString, 512, "Tried to stop Netscape service"
+ " %s: Error %d (%s)."
+ " Please stop the server from the Services Item in the"
+ " Control Panel", serviceName, Error, ds_system_errmsg());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_UNKNOWN);
+ }
+ return(DS_SERVER_DOWN);
+}
+
+
+int
+StartNetscapeService()
+{
+ CHAR ErrorString[512];
+ int retries = 0;
+ char *serviceName = ds_get_server_name();
+
+ schService = OpenService(
+ schSCManager, // SCManager database
+ serviceName, // name of service
+ SERVICE_ALL_ACCESS);
+ if (schService == NULL)
+ {
+ CloseServiceHandle(schService);
+ sprintf(ErrorString, "Tried to start"
+ " the Netscape service %s: Error %d. Please"
+ " start the server from the Services Item in the Control Panel",
+ serviceName, GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_DOWN);
+ }
+
+ if (!StartService(schService, 0, NULL))
+ {
+ CloseServiceHandle(schService);
+ sprintf(ErrorString, "StartService:Could not start "
+ "the Directory service %s: Error %d. Please restart the server "
+ "from the Services Item in the Control Panel",
+ serviceName, GetLastError());
+ ds_send_error(ErrorString, 0);
+ return(DS_SERVER_DOWN);
+ }
+
+ CloseServiceHandle(schService);
+ return(DS_SERVER_UP);
+}
+
+void
+WaitForServertoStop()
+{
+ HANDLE hServDoneSemaphore;
+ int result,retries = 0;
+ char *serviceName = ds_get_server_name();
+ char *newServiceName;
+
+RETRY:
+
+ newServiceName = (PCHAR)malloc(strlen(serviceName) + 5);
+ sprintf(newServiceName, "NS_%s\0", serviceName);
+
+ hServDoneSemaphore = CreateSemaphore(
+ NULL, // security attributes
+ 0, // initial count for semaphore
+ 1, // maximum count for semaphore
+ newServiceName);
+
+ free(newServiceName);
+
+ if ( hServDoneSemaphore == NULL) {
+ result = GetLastError();
+ if (result == ERROR_INVALID_HANDLE) {
+ if (retries < SERVER_STOP_TIMEOUT) {
+ retries++;
+ Sleep(1000);
+ goto RETRY;
+ }
+ } else {
+ /* We aren't too interested in why the creation failed
+ * if it is not because of another instance */
+ return;
+ }
+ } // hServDoneSemaphore == NULL
+ CloseHandle(hServDoneSemaphore);
+ return;
+}
+#endif
diff --git a/ldap/admin/lib/dsalib_util.c b/ldap/admin/lib/dsalib_util.c
new file mode 100644
index 00000000..a6cf4bee
--- /dev/null
+++ b/ldap/admin/lib/dsalib_util.c
@@ -0,0 +1,1123 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#if defined( XP_WIN32 )
+#include <windows.h>
+#include <io.h>
+#else /* XP_WIN32 */
+# if defined( AIXV4 )
+# include <fcntl.h>
+# else /* AIXV4 */
+# include <sys/fcntl.h>
+# endif /* AIXV4 */
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#endif /* XP_WIN3 */
+#include "dsalib.h"
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <nspr.h>
+
+#define COPY_BUFFER_SIZE 4096
+/* This is the separator string to use when outputting key/value pairs
+ to be read by the non-HTML front end (Java console)
+*/
+static const char *SEPARATOR = ":"; /* from AdmTask.java */
+
+#define LOGFILEENVVAR "DEBUG_LOGFILE" /* used for logfp */
+
+static int internal_rm_rf(const char *path, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg);
+
+/* return a FILE * opened in append mode to the log file
+ caller must use fclose to close it
+*/
+static FILE *
+get_logfp(void)
+{
+ FILE *logfp = NULL;
+ char *logfile = getenv(LOGFILEENVVAR);
+
+ if (logfile) {
+ logfp = fopen(logfile, "a");
+ }
+ return logfp;
+}
+
+DS_EXPORT_SYMBOL int
+ds_file_exists(char *filename)
+{
+ struct stat finfo;
+
+ if ( filename == NULL )
+ return 0;
+
+ if ( stat(filename, &finfo) == 0 ) /* successful */
+ return 1;
+ else
+ return 0;
+}
+
+DS_EXPORT_SYMBOL int
+ds_mkdir(char *dir, int mode)
+{
+ if(!ds_file_exists(dir)) {
+#ifdef XP_UNIX
+ if(mkdir(dir, mode) == -1)
+#else /* XP_WIN32 */
+ if(!CreateDirectory(dir, NULL))
+#endif /* XP_WIN32 */
+ return -1;
+ }
+ return 0;
+}
+
+
+DS_EXPORT_SYMBOL char *
+ds_mkdir_p(char *dir, int mode)
+{
+ static char errmsg[ERR_SIZE];
+ struct stat fi;
+ char *t;
+
+#ifdef XP_UNIX
+ t = dir + 1;
+#else /* XP_WIN32 */
+ t = dir + 3;
+#endif /* XP_WIN32 */
+
+ while(1) {
+ t = strchr(t, FILE_PATHSEP);
+
+ if(t) *t = '\0';
+ if(stat(dir, &fi) == -1) {
+ if(ds_mkdir(dir, mode) == -1) {
+ sprintf(errmsg, "mkdir %s failed (%s)", dir, ds_system_errmsg());
+ return errmsg;
+ }
+ }
+ if(t) *t++ = FILE_PATHSEP;
+ else break;
+ }
+ return NULL;
+}
+
+
+/*
+ * Given the name of a directory, return a NULL-terminated array of
+ * the file names contained in that directory. Returns NULL if the directory
+ * does not exist or an error occurs, and returns an array with a
+ * single NULL string if the directory exists but is empty. The caller
+ * is responsible for freeing the returned array of strings.
+ * File names "." and ".." are not returned.
+ */
+#if !defined( XP_WIN32 )
+DS_EXPORT_SYMBOL char **
+ds_get_file_list( char *dir )
+{
+ DIR *dirp;
+ struct dirent *direntp;
+ char **ret = NULL;
+ int nfiles = 0;
+
+ if (( dirp = opendir( dir )) == NULL ) {
+ return NULL;
+ }
+
+ if (( ret = malloc( sizeof( char * ))) == NULL ) {
+ return NULL;
+ };
+
+ while (( direntp = readdir( dirp )) != NULL ) {
+ if ( strcmp( direntp->d_name, "." ) &&
+ strcmp( direntp->d_name, ".." )) {
+ if (( ret = (char **) realloc( ret,
+ sizeof( char * ) * ( nfiles + 2 ))) == NULL );
+ ret[ nfiles ] = strdup( direntp->d_name );
+ nfiles++;
+ }
+ }
+ (void) closedir( dirp );
+
+ ret[ nfiles ] = NULL;
+ return ret;
+}
+#else
+DS_EXPORT_SYMBOL char **
+ds_get_file_list( char *dir )
+{
+ char szWildcardFileSpec[MAX_PATH];
+ char **ret = NULL;
+ long hFile;
+ struct _finddata_t fileinfo;
+ int nfiles = 0;
+
+ if( ( dir == NULL ) || (strlen( dir ) == 0) )
+ return NULL;
+
+ if( ( ret = malloc( sizeof( char * ) ) ) == NULL )
+ return NULL;
+
+ strcpy(szWildcardFileSpec, dir);
+ strcat(szWildcardFileSpec, "/*");
+
+ hFile = _findfirst( szWildcardFileSpec, &fileinfo);
+ if( hFile == -1 )
+ return NULL;
+
+ if( ( strcmp( fileinfo.name, "." ) != 0 ) &&
+ ( strcmp( fileinfo.name, ".." ) != 0 ) )
+ {
+ ret[ nfiles++ ] = strdup( fileinfo.name );
+ }
+
+ while( _findnext( hFile, &fileinfo ) == 0 )
+ {
+ if( ( strcmp( fileinfo.name, "." ) != 0 ) &&
+ ( strcmp( fileinfo.name, ".." ) != 0 ) )
+ {
+ if( ( ret = (char **) realloc( ret, sizeof( char * ) * ( nfiles + 2 ) ) ) != NULL )
+ ret[ nfiles++ ] = strdup( fileinfo.name);
+ }
+ }
+
+ _findclose( hFile );
+ ret[ nfiles ] = NULL;
+ return ret;
+}
+#endif /* ( XP_WIN32 ) */
+
+
+DS_EXPORT_SYMBOL time_t
+ds_get_mtime(char *filename)
+{
+ struct stat fi;
+
+ if ( stat(filename, &fi) )
+ return 0;
+ return fi.st_mtime;
+}
+
+/*
+ * Copy files: return is
+ * 1: success
+ * 0: failure
+ * Print errors as needed.
+ */
+DS_EXPORT_SYMBOL int
+ds_cp_file(char *sfile, char *dfile, int mode)
+{
+#if defined( XP_WIN32 )
+ return( CopyFile( sfile, dfile, FALSE ) ); /* Copy even if dfile exists */
+#else
+ int sfd, dfd, len;
+ struct stat fi;
+ char copy_buffer[COPY_BUFFER_SIZE];
+ unsigned long read_len;
+ char error[BIG_LINE];
+
+/* Make sure we're in the right umask */
+ umask(022);
+
+ if( (sfd = open(sfile, O_RDONLY)) == -1) {
+ sprintf(error, "Can't open file %s for reading.", sfile);
+ ds_send_error(error, 1);
+ return(0);
+ }
+
+ fstat(sfd, &fi);
+ if (!(S_ISREG(fi.st_mode))) {
+ sprintf(error, "File %s is not a regular file.", sfile);
+ ds_send_error(error, 1);
+ close(sfd);
+ return(0);
+ }
+ len = fi.st_size;
+
+ if( (dfd = open(dfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) {
+ sprintf(error, "can't write to file %s", dfile);
+ ds_send_error(error, 1);
+ close(sfd);
+ return(0);
+ }
+ while (len) {
+ read_len = len>COPY_BUFFER_SIZE?COPY_BUFFER_SIZE:len;
+
+ if ( (read_len = read(sfd, copy_buffer, read_len)) == -1) {
+ sprintf(error, "Error reading file %s for copy.", sfile);
+ ds_send_error(error, 1);
+ close(sfd);
+ close(dfd);
+ return(0);
+ }
+
+ if ( write(dfd, copy_buffer, read_len) != read_len) {
+ sprintf(error, "Error writing file %s for copy.", dfile);
+ ds_send_error(error, 1);
+ close(sfd);
+ close(dfd);
+ return(0);
+ }
+
+ len -= read_len;
+ }
+ close(sfd);
+ close(dfd);
+ return(1);
+#endif
+}
+
+/* Returns a directory path used for tmp files. */
+DS_EXPORT_SYMBOL char *
+ds_get_tmp_dir()
+{
+ static char tmpdir[] = "/tmp";
+ static char tmp[256] = {0};
+ unsigned ilen;
+ char pch;
+ char* instanceDir = ds_get_install_root();
+
+ if(instanceDir == NULL)
+ {
+ #if defined( XP_WIN32 )
+ ilen = strlen(tmp);
+ GetTempPath( ilen +1, tmp );
+ /* Remove trailing slash. */
+ pch = tmp[ilen-1];
+ if( pch == '\\' || pch == '/' )
+ tmp[ilen-1] = '\0';
+ return tmp;
+ #else
+ return( tmpdir );
+ #endif
+ }
+
+ sprintf(tmp,"%s/tmp",instanceDir);
+
+#if defined( XP_WIN32 )
+ for(ilen=0;ilen < strlen(tmp); ilen++)
+ {
+ if(tmp[ilen]=='/')
+ tmp[ilen]='\\';
+ }
+#endif
+
+ if(!ds_file_exists(tmp))
+ ds_mkdir_p(tmp,00770);
+
+ return ( tmp );
+}
+
+DS_EXPORT_SYMBOL void
+ds_unixtodospath(char *szText)
+{
+ if(szText)
+ {
+ while(*szText)
+ {
+ if( *szText == '/' )
+ *szText = '\\';
+ szText++;
+ }
+ }
+}
+
+/* converts '\' chars to '/' */
+DS_EXPORT_SYMBOL void
+ds_dostounixpath(char *szText)
+{
+ if(szText)
+ {
+ while(*szText)
+ {
+ if( *szText == '\\' )
+ *szText = '/';
+ szText++;
+ }
+ }
+}
+
+/* converts ':' chars to ' ' */
+DS_EXPORT_SYMBOL void
+ds_timetofname(char *szText)
+{
+ if(szText)
+ {
+ /* Replace trailing newline */
+ szText[ strlen( szText ) -1 ] = 0;
+ while(*szText)
+ {
+ if( *szText == ':' ||
+ *szText == ' ' )
+ *szText = '_';
+ szText++;
+ }
+ }
+}
+
+/* Effects a rename in 2 steps, needed on NT because if the
+target of a rename() already exists, the rename() will fail. */
+DS_EXPORT_SYMBOL int
+ds_saferename(char *szSrc, char *szTarget)
+{
+#ifdef XP_WIN32
+ int iRetVal;
+ char *szTmpFile;
+ struct stat buf;
+#endif
+
+ if( !szSrc || !szTarget )
+ return 1;
+
+#if defined( XP_WIN32 )
+
+ szTmpFile = mktemp("slrnXXXXXX" );
+ if( stat( szTarget, &buf ) == 0 )
+ {
+ /* Target file exists */
+ if( !szTmpFile )
+ return 1;
+
+ if( !ds_cp_file( szTarget, szTmpFile, 0644) )
+ return( 1 );
+
+ unlink( szTarget );
+ if( (iRetVal = rename( szSrc, szTarget )) != 0 )
+ {
+ /* Failed to rename, copy back. */
+ ds_cp_file( szTmpFile, szTarget, 0644);
+ }
+ /* Now remove temp file */
+ unlink( szTmpFile );
+ }
+ else
+ iRetVal = rename(szSrc, szTarget);
+
+ return iRetVal;
+#else
+ return rename(szSrc, szTarget);
+#endif
+
+}
+
+DS_EXPORT_SYMBOL char*
+ds_encode_all (const char* s)
+{
+ char* r;
+ size_t l;
+ size_t i;
+ if (s == NULL || *s == '\0') {
+ return strdup ("");
+ }
+ l = strlen (s);
+ r = malloc (l * 3 + 1);
+ for (i = 0; *s != '\0'; ++s) {
+ r[i++] = '%';
+ sprintf (r + i, "%.2X", 0xFF & (unsigned int)*s);
+ i += 2;
+ }
+ r[i] = '\0';
+ return r;
+}
+
+DS_EXPORT_SYMBOL char*
+ds_URL_encode (const char* s)
+{
+ char* r;
+ size_t l;
+ size_t i;
+ if (s == NULL || *s == '\0') {
+ return strdup ("");
+ }
+ l = strlen (s) + 1;
+ r = malloc (l);
+ for (i = 0; *s != '\0'; ++s) {
+ if (*s >= 0x20 && *s <= 0x7E && strchr (" <>\"#%{}[]|\\^~`?,;=+\n", *s) == NULL) {
+ if (l - i <= 1) r = realloc (r, l *= 2);
+ r[i++] = *s;
+ } else { /* encode *s */
+ if (l - i <= 3) r = realloc (r, l *= 2);
+ r[i++] = '%';
+ sprintf (r + i, "%.2X", 0xFF & (unsigned int)*s);
+ i += 2;
+ }
+ }
+ r[i] = '\0';
+ return r;
+}
+
+DS_EXPORT_SYMBOL char*
+ds_URL_decode (const char* original)
+{
+ char* r = strdup (original);
+ char* s;
+ for (s = r; *s != '\0'; ++s) {
+ if (*s == '+') {
+ *s = ' ';
+ }
+ else if (*s == '%' && isxdigit(s[1]) && isxdigit(s[2])) {
+ memmove (s, s+1, 2);
+ s[2] = '\0';
+ *s = (char)strtoul (s, NULL, 16);
+ memmove (s+1, s+3, strlen (s+3) + 1);
+ }
+ }
+ return r;
+}
+
+#if !defined( XP_WIN32 )
+#include <errno.h> /* errno */
+#include <pwd.h> /* getpwnam */
+
+static int saved_uid_valid = 0;
+static uid_t saved_uid;
+static int saved_gid_valid = 0;
+static gid_t saved_gid;
+
+#if defined( HPUX )
+#define SETEUID(id) setresuid((uid_t) -1, id, (uid_t) -1)
+#else
+#define SETEUID(id) seteuid(id)
+#endif
+
+#endif
+
+DS_EXPORT_SYMBOL char*
+ds_become_localuser_name (char *localuser)
+{
+#if !defined( XP_WIN32 )
+ if (localuser != NULL) {
+ struct passwd* pw = getpwnam (localuser);
+ if (pw == NULL) {
+ fprintf (stderr, "getpwnam(%s) == NULL; errno %d",
+ localuser, errno);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ } else {
+ if ( ! saved_uid_valid) saved_uid = geteuid();
+ if ( ! saved_gid_valid) saved_gid = getegid();
+ if (setgid (pw->pw_gid) == 0) {
+ saved_gid_valid = 1;
+ } else {
+ fprintf (stderr, "setgid(%li) != 0; errno %d",
+ (long)pw->pw_gid, errno);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ if (SETEUID (pw->pw_uid) == 0) {
+ saved_uid_valid = 1;
+ } else {
+ fprintf (stderr, "seteuid(%li) != 0; errno %d",
+ (long)pw->pw_uid, errno);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ }
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+DS_EXPORT_SYMBOL char*
+ds_become_localuser (char **ds_config)
+{
+#if !defined( XP_WIN32 )
+ char* localuser = ds_get_value (ds_config, ds_get_var_name(DS_LOCALUSER), 0, 1);
+ if (localuser != NULL) {
+ char *rv = ds_become_localuser_name(localuser);
+
+ free(localuser);
+ return rv;
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+DS_EXPORT_SYMBOL char*
+ds_become_original (char **ds_config)
+{
+#if !defined( XP_WIN32 )
+ if (saved_uid_valid) {
+ if (SETEUID (saved_uid) == 0) {
+ saved_uid_valid = 0;
+ } else {
+ fprintf (stderr, "seteuid(%li) != 0; errno %d<br>n",
+ (long)saved_uid, errno);
+ fflush (stderr);
+ }
+ }
+ if (saved_gid_valid) {
+ if (setgid (saved_gid) == 0) {
+ saved_gid_valid = 0;
+ } else {
+ fprintf (stderr, "setgid(%li) != 0; errno %d<br>\n",
+ (long)saved_gid, errno);
+ fflush (stderr);
+ }
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * When a path containing a long filename is passed to system(), the call
+ * fails. Therfore, we need to use the short version of the path, when
+ * constructing the path to pass to system().
+ */
+DS_EXPORT_SYMBOL char*
+ds_makeshort( char * filepath )
+{
+#if defined( XP_WIN32 )
+ char *shortpath = malloc( MAX_PATH );
+ DWORD dwStatus;
+ if( shortpath )
+ {
+ dwStatus = GetShortPathName( filepath, shortpath, MAX_PATH );
+ return( shortpath );
+ }
+#endif
+ return filepath;
+}
+
+/* returns 1 if string "searchstring" found in file "filename" */
+DS_EXPORT_SYMBOL int
+ds_search_file(char *filename, char *searchstring)
+{
+ struct stat finfo;
+ FILE * sf;
+ char big_line[BIG_LINE];
+
+ if( filename == NULL )
+ return 0;
+
+ if( stat(filename, &finfo) != 0 ) /* successful */
+ return 0;
+
+ if( !(sf = fopen(filename, "r")) )
+ return 0;
+
+ while ( fgets(big_line, BIG_LINE, sf) ) {
+ if( strstr( big_line, searchstring ) != NULL ) {
+ fclose(sf);
+ return 1;
+ }
+ }
+
+ fclose(sf);
+
+ return 0;
+}
+
+/*
+ * on linux when running as root, doing something like
+ * system("date > out.log 2>&1") will fail, because of an
+ * ambigious redirect. This works for /bin/sh, but not /bin/csh or /bin/tcsh
+ *
+ * using this would turn
+ * system("date > out.log 2>&1");
+ * into
+ * system("/bin/sh/ -c \"date > out.log 2>&1\"")
+ *
+ */
+DS_EXPORT_SYMBOL void
+alter_startup_line(char *startup_line)
+{
+#if (defined Linux && !defined LINUX2_4)
+ char temp_startup_line[BIG_LINE+40];
+
+ sprintf(temp_startup_line, "/bin/sh -c \"%s\"", startup_line);
+ strcpy(startup_line, temp_startup_line);
+#else
+ /* do nothing */
+#endif /* Linux */
+}
+
+DS_EXPORT_SYMBOL void
+ds_send_error(char *errstr, int print_errno)
+{
+ FILE *logfp;
+ fprintf(stdout, "error%s%s\n", SEPARATOR, errstr);
+ if (print_errno && errno)
+ fprintf(stdout, "system_errno%s%d\n", SEPARATOR, errno);
+
+ fflush(stdout);
+
+ if (logfp = get_logfp()) {
+ fprintf(logfp, "error%s%s\n", SEPARATOR, errstr);
+ if (print_errno && errno)
+ fprintf(logfp, "system_errno%s%d\n", SEPARATOR, errno);
+ fclose(logfp);
+ }
+
+}
+
+DS_EXPORT_SYMBOL void
+ds_send_status(char *str)
+{
+ FILE *logfp;
+ fprintf(stdout, "[%s]: %s\n", ds_get_server_name(), str);
+ fflush(stdout);
+
+ if (logfp = get_logfp()) {
+ fprintf(logfp, "[%s]: %s\n", ds_get_server_name(), str);
+ fclose(logfp);
+ }
+}
+
+/* type and doexit are unused
+ I'm not sure what type is supposed to be used for
+ removed the doexit code because we don't want to
+ exit abruptly anymore, we must exit by returning an
+ exit code from the return in main()
+*/
+static void
+report_error(int type, char *msg, char *details, int doexit)
+{
+ char error[BIG_LINE*4] = {0};
+
+ if (msg)
+ {
+ strcat(error, msg);
+ strcat(error, SEPARATOR);
+ }
+ if (details)
+ strcat(error, details);
+ ds_send_error(error, 1);
+}
+
+DS_EXPORT_SYMBOL void
+ds_report_error(int type, char *msg, char *details)
+{
+ /* richm - changed exit flag to 0 - we must not exit
+ abruptly, we should instead exit by returning a code
+ as the return value of main - this ensures that callers
+ are properly notified of the status
+ */
+ report_error(type, msg, details, 0);
+}
+
+DS_EXPORT_SYMBOL void
+ds_report_warning(int type, char *msg, char *details)
+{
+ report_error(type, msg, details, 0);
+}
+
+DS_EXPORT_SYMBOL void
+ds_show_message(const char *message)
+{
+ FILE *logfp;
+ printf("%s\n", message);
+ fflush(stdout);
+
+ if (logfp = get_logfp()) {
+ fprintf(logfp, "%s\n", message);
+ fclose(logfp);
+ }
+
+ return;
+}
+
+DS_EXPORT_SYMBOL void
+ds_show_key_value(char *key, char *value)
+{
+ FILE *logfp;
+ printf("%s%s%s\n", key, SEPARATOR, value);
+
+ if (logfp = get_logfp()) {
+ fprintf(logfp, "%s%s%s\n", key, SEPARATOR, value);
+ fclose(logfp);
+ }
+ return;
+}
+
+/* Stolen from the Admin Server dsgw_escape_for_shell */
+DS_EXPORT_SYMBOL char *
+ds_escape_for_shell( char *s )
+{
+ char *escaped;
+ char tmpbuf[4];
+ size_t x,l;
+
+ if ( s == NULL ) {
+ return( s );
+ }
+
+ l = 3 * strlen( s ) + 1;
+ escaped = malloc( l );
+ memset( escaped, 0, l );
+ for ( x = 0; s[x]; x++ ) {
+ if (( (unsigned char)s[x] & 0x80 ) == 0 ) {
+ strncat( escaped, &s[x], 1 );
+ } else {
+ /* not an ASCII character - escape it */
+ sprintf( tmpbuf, "\\%x", (unsigned)(((unsigned char)(s[x])) & 0xff) );
+ strcat( escaped, tmpbuf );
+ }
+ }
+ return( escaped );
+}
+
+DS_EXPORT_SYMBOL char *
+ds_system_errmsg(void)
+{
+ static char static_error[BUFSIZ];
+ char *lmsg = 0; /* Local message pointer */
+ size_t msglen = 0;
+ int sys_error = 0;
+#ifdef XP_WIN32
+ LPTSTR sysmsg = 0;
+#endif
+
+ /* Grab the OS error message */
+#ifdef XP_WIN32
+ sys_error = GetLastError();
+#else
+ sys_error = errno;
+#endif
+
+#if defined(XP_WIN32)
+ msglen = FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ GetLastError(),
+ LOCALE_SYSTEM_DEFAULT,
+ (LPTSTR)&sysmsg,
+ 0,
+ 0);
+ if (msglen > 0)
+ lmsg = sysmsg;
+ SetLastError(0);
+#else
+ lmsg = strerror(errno);
+ errno = 0;
+#endif
+
+ if (!lmsg)
+ static_error[0] = 0;
+ else
+ {
+ /* At this point lmsg points to something. */
+ int min = 0;
+ msglen = strlen(lmsg);
+
+ min = msglen > BUFSIZ ? BUFSIZ : msglen;
+ strncpy(static_error, lmsg, min);
+ static_error[min-1] = 0;
+ }
+
+#ifdef XP_WIN32
+ /* NT's FormatMessage() dynamically allocated the msg; free it */
+ if (sysmsg)
+ LocalFree(sysmsg);
+#endif
+
+ return static_error;
+}
+
+/* get db path dir info from dse.ldif and remove it if it's not under path
+*/
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+enum {
+ DB_DIRECTORY = 0,
+ DB_LOGDIRECTORY,
+ DB_CHANGELOGDIRECTORY,
+ DB_HOME_DIRECTORY
+};
+
+static int
+is_fullpath(char *path)
+{
+ int len;
+ if (NULL == path || '\0' == *path)
+ return 0;
+
+ if (FILE_PATHSEP == *path) /* UNIX */
+ return 1;
+
+ len = strlen(path);
+ if (len > 2)
+ {
+ if (':' == path[1] && ('/' == path[2] || '\\' == path[2])) /* Windows */
+ return 1;
+ }
+ return 0;
+}
+
+static void
+rm_db_dirs(char *fullpath, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg)
+{
+ FILE *fp = fopen(fullpath, "r");
+ char buf[2][MAXPATHLEN];
+ char rmbuf[MAXPATHLEN];
+ char *bufp, *nextbufp;
+ char *retp;
+ int readit = 0;
+
+ if (fp == NULL)
+ {
+ ds_rm_rf_err_func(fullpath, "opening dse.ldif", arg);
+ return;
+ }
+
+ bufp = buf[0]; *bufp = '\0';
+ nextbufp = buf[1]; *nextbufp = '\0';
+
+ while (readit || (retp = fgets(bufp, MAXPATHLEN, fp)) != NULL)
+ {
+ int len = strlen(bufp);
+ int type = -1;
+ char *p, *q;
+
+ if (strstr(bufp, "nsslapd-directory"))
+ type = DB_DIRECTORY;
+ else if (strstr(bufp, "nsslapd-db-home-directory"))
+ type = DB_HOME_DIRECTORY;
+ else if (strstr(bufp, "nsslapd-db-logdirectory"))
+ type = DB_LOGDIRECTORY;
+ else if (strstr(bufp, "nsslapd-changelogdir"))
+ type = DB_CHANGELOGDIRECTORY;
+ else
+ {
+ readit = 0;
+ continue;
+ }
+
+ p = bufp + len;
+
+ while ((retp = fgets(nextbufp, MAXPATHLEN, fp)) != NULL)
+ {
+ int thislen;
+ if (*nextbufp == ' ')
+ {
+ thislen = strlen(nextbufp);
+ len += thislen;
+ if (len < MAXPATHLEN)
+ {
+ strncpy(p, nextbufp, thislen);
+ p += thislen;
+ }
+ /* else too long as a path. ignore it */
+ }
+ else
+ break;
+ }
+ if (retp == NULL) /* done */
+ break;
+
+ p = strchr(bufp, ':');
+ if (p == NULL)
+ {
+ char *tmpp = bufp;
+ bufp = nextbufp;
+ nextbufp = tmpp;
+ readit = 1;
+ continue;
+ }
+
+ while (*(++p) == ' ') ;
+
+ q = p + strlen(p) - 1;
+ while (*q == ' ' || *q == '\t' || *q == '\n')
+ q--;
+ *(q+1) = '\0';
+
+ switch (type)
+ {
+ case DB_DIRECTORY:
+ case DB_LOGDIRECTORY:
+ case DB_CHANGELOGDIRECTORY:
+ if (is_fullpath(p))
+ internal_rm_rf(p, ds_rm_rf_err_func, NULL);
+ break;
+ case DB_HOME_DIRECTORY:
+ internal_rm_rf(p, ds_rm_rf_err_func, NULL);
+ break;
+ }
+ }
+
+ fclose(fp);
+}
+
+/* this function will recursively remove a directory hierarchy from the file
+ system, like "rm -rf"
+ In order to handle errors, the user supplies a callback function. When an
+ error occurs, the callback function is called with the file or directory name
+ and the system errno. The callback function should return TRUE if it wants
+ to continue or FALSE if it wants the remove aborted.
+ The error callback should use PR_GetError and/or PR_GetOSError to
+ determine the cause of the failure
+*/
+/* you could locate db dirs non standard location
+ we should remove them, as well.
+*/
+static int
+internal_rm_rf(const char *path, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg)
+{
+ struct PRFileInfo prfi;
+ char *fullpath = NULL;
+ int retval = 0;
+
+ if (PR_GetFileInfo(path, &prfi) != PR_SUCCESS) {
+ if (!ds_rm_rf_err_func(path, "reading directory", arg)) {
+ return 1;
+ }
+ }
+
+ if (prfi.type == PR_FILE_DIRECTORY)
+ {
+ PRDir *dir;
+ PRDirEntry *dirent;
+
+ if (!(dir = PR_OpenDir(path))) {
+ if (!ds_rm_rf_err_func(path, "opening directory", arg)) {
+ return 1;
+ }
+ return 0;
+ }
+
+ while (dirent = PR_ReadDir(dir, PR_SKIP_BOTH)) {
+ char *fullpath = PR_smprintf("%s%c%s", path, FILE_PATHSEP, dirent->name);
+ if (PR_GetFileInfo(fullpath, &prfi) != PR_SUCCESS) {
+ if (!ds_rm_rf_err_func(fullpath, "reading file", arg)) {
+ PR_smprintf_free(fullpath);
+ PR_CloseDir(dir);
+ return 1;
+ } /* else just continue */
+ } else if (prfi.type == PR_FILE_DIRECTORY) {
+ retval = internal_rm_rf(fullpath, ds_rm_rf_err_func, arg);
+ if (retval) { /* non zero return means stop */
+ PR_smprintf_free(fullpath);
+ break;
+ }
+ } else {
+ /* if dse.ldif, check db dir is under the instance dir or not */
+ if (0 == strcmp(dirent->name, "dse.ldif"))
+ rm_db_dirs(fullpath, ds_rm_rf_err_func, arg);
+
+ if (PR_Delete(fullpath) != PR_SUCCESS) {
+ if (!ds_rm_rf_err_func(fullpath, "deleting file", arg)) {
+ PR_smprintf_free(fullpath);
+ PR_CloseDir(dir);
+ return 1;
+ }
+ }
+ }
+ PR_smprintf_free(fullpath);
+ }
+ PR_CloseDir(dir);
+ if (PR_RmDir(path) != PR_SUCCESS) {
+ if (!ds_rm_rf_err_func(path, "removing directory", arg)) {
+ retval = 1;
+ }
+ }
+ }
+
+ return retval;
+}
+
+static int
+default_err_func(const char *path, const char *op, void *arg)
+{
+ PRInt32 errcode = PR_GetError();
+ char *msg;
+ const char *errtext;
+
+ if (!errcode || (errcode == PR_UNKNOWN_ERROR)) {
+ errcode = PR_GetOSError();
+ errtext = ds_system_errmsg();
+ } else {
+ errtext = PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT);
+ }
+
+ msg = PR_smprintf("%s %s: error code %d (%s)", op, path, errcode, errtext);
+ ds_send_error(msg, 0);
+ PR_smprintf_free(msg);
+ return 1; /* just continue */
+}
+
+DS_EXPORT_SYMBOL int
+ds_rm_rf(const char *dir, DS_RM_RF_ERR_FUNC ds_rm_rf_err_func, void *arg)
+{
+ int retval = 0;
+ struct PRFileInfo prfi;
+
+ if (!dir) {
+ ds_send_error("Could not remove NULL directory name", 1);
+ return 1;
+ }
+
+ if (!ds_rm_rf_err_func) {
+ ds_rm_rf_err_func = default_err_func;
+ }
+
+ if (PR_GetFileInfo(dir, &prfi) != PR_SUCCESS) {
+ if (ds_rm_rf_err_func(dir, "reading directory", arg)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ if (prfi.type != PR_FILE_DIRECTORY) {
+ char *msg = PR_smprintf("Cannot remove directory %s because it is not a directory", dir);
+ ds_send_error(msg, 0);
+ PR_smprintf_free(msg);
+ return 1;
+ }
+
+ return internal_rm_rf(dir, ds_rm_rf_err_func, arg);
+}
+
+DS_EXPORT_SYMBOL int
+ds_remove_reg_key(void *base, const char *format, ...)
+{
+ int rc = 0;
+#ifdef XP_WIN32
+ int retries = 3;
+ HKEY hkey = (HKEY)base;
+ char *key;
+ va_list ap;
+
+ va_start(ap, format);
+ key = PR_vsmprintf(format, ap);
+ va_end(ap);
+
+ do {
+ if (ERROR_SUCCESS != RegDeleteKey(hkey, key)) {
+ rc = GetLastError();
+ if (rc == ERROR_BADKEY || rc == ERROR_CANTOPEN ||
+ rc == ERROR_CANTREAD ||
+ rc == ERROR_CANTWRITE || rc == ERROR_KEY_DELETED ||
+ rc == ERROR_ALREADY_EXISTS || rc == ERROR_NO_MORE_FILES) {
+ rc = 0; /* key already deleted - no error */
+ } else if ((retries > 1) && (rc == ERROR_IO_PENDING)) {
+ /* the key is busy - lets wait and try again */
+ PR_Sleep(PR_SecondsToInterval(3));
+ retries--;
+ } else {
+ char *errmsg = PR_smprintf("Could not remove registry key %s - error %d (%s)",
+ key, rc, ds_system_errmsg());
+ ds_send_error(errmsg, 0);
+ PR_smprintf_free(errmsg);
+ break; /* no retry, just fail */
+ }
+ }
+ } while (rc && retries);
+ PR_smprintf_free(key);
+#endif
+ return rc;
+}