[Fedora-directory-commits] ldapserver/ldap/admin/src/scripts template-bak2db.pl.in, NONE, 1.1 template-cl-dump.pl.in, NONE, 1.1 template-db2bak.pl.in, NONE, 1.1 template-db2index.pl.in, NONE, 1.1 template-db2ldif.pl.in, NONE, 1.1 template-ldif2db.pl.in, NONE, 1.1 template-ns-accountstatus.pl.in, NONE, 1.1 template-ns-activate.pl.in, NONE, 1.1 template-ns-inactivate.pl.in, NONE, 1.1 template-ns-newpwpolicy.pl.in, NONE, 1.1 template-repl-monitor-cgi.pl.in, NONE, 1.1 template-repl-monitor.pl.in, NONE, 1.1 template-verify-db.pl.in, NONE, 1.1 template-cl-dump.pl, 1.8, 1.9 template-ns-newpwpolicy.pl, 1.6, 1.7 template-repl-monitor-cgi.pl, 1.6, 1.7 template-verify-db.pl, 1.6, 1.7

Noriko Hosoi (nhosoi) fedora-directory-commits at redhat.com
Wed Oct 25 20:36:54 UTC 2006


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/admin/src/scripts
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv5158/ldap/admin/src/scripts

Modified Files:
	template-cl-dump.pl template-ns-newpwpolicy.pl 
	template-repl-monitor-cgi.pl template-verify-db.pl 
Added Files:
	template-bak2db.pl.in template-cl-dump.pl.in 
	template-db2bak.pl.in template-db2index.pl.in 
	template-db2ldif.pl.in template-ldif2db.pl.in 
	template-ns-accountstatus.pl.in template-ns-activate.pl.in 
	template-ns-inactivate.pl.in template-ns-newpwpolicy.pl.in 
	template-repl-monitor-cgi.pl.in template-repl-monitor.pl.in 
	template-verify-db.pl.in 
Log Message:
Resolves: #212098
Summary: Use autoconf to generate task perl script templates
Changes:
1) added template files to AC_CONFIG_FILES list
2) added db_bindir and ldapsdk_bindir to pass their tools path to the template
files.	The paths are hardcoded for now.



--- NEW FILE template-bak2db.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub usage {
	print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
	print(STDERR "     :    -a dirname [-t dbtype]\n");
	print(STDERR " Opts: -D rootdn   - Directory Manager\n");
	print(STDERR "     : -w password - Directory Manager's password\n");
	print(STDERR "     : -w -        - Prompt for Directory Manager's password\n");
	print(STDERR "     : -j filename - Read Directory Manager's password from file\n");
	print(STDERR "     : -a dirname  - backup directory\n");
	print(STDERR "     : -t dbtype   - database type (default: ldbm database)\n");
	print(STDERR "     : -n backend  - name of backend instance to restore\n");
	print(STDERR "     : -v          - verbose\n");
}
$taskname = "";
$archivedir = "";
$dbtype = "ldbm database";
$instance = "";
$prefix = "{{DS-ROOT}}";
$verbose = 0;
$rootdn = "";
$passwd = "";
$passwdfile = "";
$i = 0;
while ($i <= $#ARGV) {
	if ("$ARGV[$i]" eq "-a") {	# backup directory
		$i++; $archivedir = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-D") {	# Directory Manager
		$i++; $rootdn = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-w") {	# Directory Manager's password
		$i++; $passwd = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-j") { # Read Directory Manager's password from a file
		$i++; $passwdfile = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-t") {	# database type
		$i++; $dbtype = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-n") {	# backend instance name
		$i++; $instance = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-v") {	# verbose
		$verbose = 1;
	} else {
		&usage; exit(1);
	}
	$i++;
}
if ($passwdfile ne ""){
# Open file and get the password
	unless (open (RPASS, $passwdfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$passwd = <RPASS>;
	chomp($passwd);
	close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$passwd = ReadLine(0); 
#	chomp($passwd);
#	ReadMode('normal');
}
if ( $rootdn eq "" || $passwd eq "") { &usage; exit(1); }
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "restore_${yr}_${mn}_${dy}_${h}_${m}_${s}";
if ($archivedir eq "") {
	&usage; exit(1);
}
use File::Spec;
$isabs = File::Spec->file_name_is_absolute( $archivedir );
if (!$isabs) {
    $archivedir = File::Spec->rel2abs( $archivedir );
}
$dn = "dn: cn=$taskname, cn=restore, cn=tasks, cn=config\n";
$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
$cn = "cn: $taskname\n";
if ($instance ne "") {
	$nsinstance = "nsInstance: ${instance}\n";
}
$nsarchivedir = "nsArchiveDir: $archivedir\n";
$nsdbtype = "nsDatabaseType: $dbtype\n";
$entry = "${dn}${misc}${cn}${nsinstance}${nsarchivedir}${nsdbtype}";
$vstr = "";
if ($verbose != 0) { $vstr = "-v"; }
$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
print(FOO "$entry");
close(FOO);


--- NEW FILE template-cl-dump.pl.in ---
#{{PERL-EXEC}}
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
###################################################################################
#
# FILE: cl-dump.pl
#
# SYNOPSIS:
#
#    cl-dump.pl [-h host] [-p port] [-D bind-dn] -w bind-password | -P bind-cert\
#		[-r replica-roots] [-o output-file] [-c] [-v]\n";
#
#    cl-dump.pl -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]\n";
#
# DESCRIPTION:
#    Dump and decode Directory Server replication change log
#
# OPTIONS:
#
#    -c Dump and interpret CSN only. This option can be used with or
#	without -i option. 
#
#    -D bind-dn
#	Directory server's bind DN. Default to "cn=Directory Manager" if
#	the option is omitted.
#
#    -h host
#	Directory server's host. Default to the server where the script
#	is running.
#
#    -i changelog-ldif-file-with-base64encoding
#	If you already have a ldif-like changelog, but the changes
#	in that file are encoded, you may use this option to
#	decode that ldif-like changelog.
#
#    -o output-file
#	Path name for the final result. Default to STDOUT if omitted.
#
#    -p port
#	Directory server's port. Default to 389.
#
#    -P bind-cert
#	Pathname of binding certificate DB
#
#    -r replica-roots
#	Specify replica roots whose changelog you want to dump. The replica
#	roots may be seperated by comma. All the replica roots would be
#	dumped if the option is omitted.
#
#    -v Print the version of this script.
#
#    -w bind-password
#	Password for the bind DN
#
# RESTRICTION:
#    If you are not using -i option, the script should be run when the server
#    is running, and from where the server's changelog directory is accessible.
#
# DIAGNOSIS:
#    For environment variable issues, see script template-repl-monitor.pl under
#    DSHOME/bin/slapd/admin/scripts
#
################################################################################
# enable the use of our bundled perldap with our bundled ldapsdk libraries
# all of this nonsense can be omitted if the mozldapsdk and perldap are
# installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5)
$prefix = "{{DS-ROOT}}";

$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

$usage="Usage: $0 [-h host] [-p port] [-D bind-dn] [-w bind-password | -P bind-cert] [-r replica-roots] [-o output-file] [-c] [-v]\n\n       $0 -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]";

use Getopt::Std;			# Parse command line arguments
use Mozilla::LDAP::Conn;		# LDAP module for Perl
use Mozilla::LDAP::Utils;		# LULU, utilities.
use Mozilla::LDAP::API;			# Used to parse LDAP URL
use MIME::Base64;			# Decode

# Global variables

$version = "Directory Server Changelog Dump - Version 1.0";

#main
{
	# Turn off buffered I/O
	$| = 1;

	# Check for legal options
	if (!getopts('h:p:D:w:P:r:o:cvi:')) {
		print $usage;
		exit -1;
	}

	exit -1 if &validateArgs;

	if ($opt_v) {
		print OUTPUT "$version\n";
		exit;
	}

	if (!$opt_i) {
		&cl_dump_and_decode;
	}
	elsif ($opt_c) {
		&grep_csn ($opt_i);
	}
	else {
		&cl_decode ($opt_i);
	}

	close (OUTPUT);
}

# Validate the parameters
sub validateArgs
{
	my ($rc) = 0;

	%ld = Mozilla::LDAP::Utils::ldapArgs();
	chop ($ld{host} = `hostname`) if !$opt_h;
	$ld{bind} = "cn=Directory Manager" if !$opt_D;
	@allreplicas = ($opt_r) if ($opt_r);
	if ($opt_o && ! open (OUTPUT, ">$opt_o")) {
		print "Can't create output file $opt_o\n";
		$rc = -1;
	} 
	# Open STDOUT if option -o is missing
	open (OUTPUT, ">-") if !$opt_o;

	return $rc;
}

# Dump and decode changelog
# OUTPUT should have been opened before this call
sub cl_dump_and_decode
{
	# Open the connection
	my ($conn) = new Mozilla::LDAP::Conn (\%ld);
	if (!$conn) {
		print OUTPUT qq/Can't connect to $ld{host}:$ld{port} as "$ld{bind}"\n/;
		return -1;
	}

	# Get the changelog dir
	my ($changelogdir);
	my ($entry) = $conn->search ("cn=changelog5,cn=config", "sub", "(objectClass=*)");
	while ($entry) {
		$changelogdir = $entry->{"nsslapd-changelogdir"}[0];
		last if $changelogdir;
		$entry = $conn->nextEntry ();
	}

	# Get all the replicas on the server if -r option is not specified
	if (!$opt_r) {
		$entry = $conn->search ("cn=mapping tree,cn=config", "sub",
								"(objectClass=nsDS5Replica)");
		while ($entry) {
			push (@allreplicas, "$entry->{nsDS5ReplicaRoot}[0]");
			$entry = $conn->nextEntry ();
		}
	}

	# Dump the changelog for the replica
	my (@ldifs);
	my ($replica);
	my ($gotldif);
	my ($ldif);
	foreach (@allreplicas) {
		# Reset the script's start time
		$^T = time;

		$replica = $_;
		$gotldif = 0;

		# Can't move this line before entering the loop:
		# no ldif file generated other than for the first
		# replica.
		$entry = $conn->newEntry();
		$entry->setDN ("cn=replica,cn=\"$_\",cn=mapping tree,cn=config");
		$entry->setValues('nsDS5Task', 'CL2LDIF');
		$conn->update ($entry);

		#Decode the dumped changelog
		@ldifs = <$changelogdir/*.ldif>;
		foreach (@ldifs) {
			# Skip older ldif files
			next if ($#ldifs > 0 && (-M $_ > 0));
			$ldif = $_;
			$gotldif = 1;
			&print_header ($replica, 0);
			if ($opt_c) {
				&grep_csn ($_);
			}
			else {
				&cl_decode ($_);
			}
			# Test op -M doesn't work well so we use rename
			# here to avoid reading the same ldif file more
			# than once.
			rename ($ldif, "$ldif.done");
		}
		&print_header ($replica, "Not Found") if !$gotldif;
	}
	$conn->close;
}

sub print_header
{
	my ($replica, $ldif) = @_;
	print OUTPUT "\n# Replica Root: $replica" if $replica;
	print OUTPUT "\n# LDIF File   : $ldif\n" if $ldif;
}

# Grep and interpret CSNs
# OUTPUT should have been opened before this call
sub grep_csn
{
	open (INPUT, "@_") || return;
	&print_header (0, @_);

	my ($csn, $maxcsn, $modts);
	while (<INPUT>) {
		next if ($_ !~ /(csn:)|(ruv:)/i);
		if (/ruv:\s*{.+}\s+(\w+)\s+(\w+)\s+(\w*)/i) {
			#
			# RUV with two CSNs and an optional lastModifiedTime
			#
			$csn = &csn_to_string($1);
			$maxcsn = &csn_to_string($2);
			$modts = $3;
			if ( $modts =~ /^0+$/ ) {
				$modts = "";
			}
			else {
				$modts = &csn_to_string($modts);
			}
		}
		elsif (/csn:\s*(\w+)\s+/i || /ruv:\s*{.+}\s+(\w+)\s+/i) {
			#
			# Single CSN
			#
			$csn = &csn_to_string($1);
			$maxcsn = "";
			$modts = "";
		}
		else {
			printf OUTPUT;
			next;
		}
		chop;
		printf OUTPUT "$_ ($csn";
		printf OUTPUT "; $maxcsn" if $maxcsn;
		printf OUTPUT "; $modts" if $modts;
		printf OUTPUT ")\n";
	}
}

sub csn_to_string
{
	my ($csn, $tm, $seq, $masterid, $subseq);
	my ($sec, $min, $hour, $mday, $mon, $year);

	$csn = "@_";
	return $csn if !$csn;

	($tm, $seq, $masterid, $subseq) = unpack("a8 a4 a4 a4", $csn);
	$tm = hex($tm);
	$seq = hex($seq);
	$masterid = hex($masterid);
	$subseq = hex($subseq);
	($sec, $min, $hour, $mday, $mon, $year) = localtime ($tm);
	$mon++;
	$year += 1900;
	foreach ($sec, $min, $hour, $mday, $mon) {
		$_ = "0".$_ if ($_ < 10);
	}
	$csn = "$mon/$mday/$year $hour:$min:$sec";
	$csn .= " $seq $subseq" if ( $seq != 0 || $subseq != 0 );

	return $csn;
}

# Decode the changelog
# OUTPUT should have been opened before this call
sub cl_decode
{
	open (INPUT, "@_") || return;
	&print_header (0, @_);

	my ($encoded);
	undef $encoded;
	while (<INPUT>) {
		# Try to accomodate "changes" in 4.X and "change" in 6.X
		if (/^changes?::\s*(\S*)/i) {
			print OUTPUT "change::\n";
			$encoded = $1;
			next;
		}
		if (!defined ($encoded)) {
			print OUTPUT;
			next;
		}
 		if ($_ eq "\n") {
			print OUTPUT MIME::Base64::decode($encoded);
			print OUTPUT "\n";
			undef $encoded;
			next;
		}
		/^\s*(\S+)\s*\n/;
		$encoded .= $1;
	}
}


--- NEW FILE template-db2bak.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub usage {
	print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
	print(STDERR "          [-a dirname] [-t dbtype]\n");
	print(STDERR " Opts: -D rootdn   - Directory Manager\n");
	print(STDERR "     : -w password - Directory Manager's password\n");
	print(STDERR "     : -w -        - Prompt for Directory Manager's password\n");
	print(STDERR "     : -j filename - Read Directory Manager's password from file\n");
	print(STDERR "     : -a dirname  - backup directory\n");
	print(STDERR "     : -t dbtype   - database type (default: ldbm database)\n");
	print(STDERR "     : -v          - verbose\n");
}
$taskname = "";
$archivedir = "";
$dbtype = "ldbm database";
$prefix = "{{DS-ROOT}}";
$mybakdir = "{{BAK-DIR}}";
$verbose = 0;
$rootdn = "";
$passwd = "";
$passwdfile = "";
$i = 0;
while ($i <= $#ARGV) {
	if ("$ARGV[$i]" eq "-a") {	# backup directory
		$i++; $archivedir = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-D") {	# Directory Manager
		$i++; $rootdn = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-w") {	# Directory Manager's password
		$i++; $passwd = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-j") { # Read Directory Manager's password from a file
		$i++; $passwdfile = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-t") {	# database type
		$i++; $dbtype = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-v") {	# verbose
		$verbose = 1;
	} else {
		&usage; exit(1);
	}
	$i++;
}
if ($passwdfile ne ""){
# Open file and get the password
	unless (open (RPASS, $passwdfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$passwd = <RPASS>;
	chomp($passwd);
	close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$passwd = ReadLine(0); 
#	chomp($passwd);
#	ReadMode('normal');
}
if ( $rootdn eq "" || $passwd eq "") { &usage; exit(1); }
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "backup_${yr}_${mn}_${dy}_${h}_${m}_${s}";
if ($archivedir eq "") {
	$archivedir = "${bakdir}{{SEP}}bak{{SEP}}${yr}_${mn}_${dy}_${h}_${m}_${s}";
}
$dn = "dn: cn=$taskname, cn=backup, cn=tasks, cn=config\n";
$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
$cn = "cn: $taskname\n";
$nsarchivedir = "nsArchiveDir: $archivedir\n";
$nsdbtype = "nsDatabaseType: $dbtype\n";
$entry = "${dn}${misc}${cn}${nsarchivedir}${nsdbtype}";
$vstr = "";
if ($verbose != 0) { $vstr = "-v"; }
$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
print(FOO "$entry");
close(FOO);


--- NEW FILE template-db2index.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub usage {
    print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
    print(STDERR "        -n instance [-t attributeName[:indextypes[:matchingrules]]]\n");
    print(STDERR " Opts: -D rootdn          - Directory Manager\n");
    print(STDERR "     : -w password        - Directory Manager's password\n");
    print(STDERR "     : -w -               - Prompt for Directory Manager's password\n");
    print(STDERR "     : -j filename        - Read Directory Manager's password from file\n");
    print(STDERR "     : -n instance        - instance to be indexed\n");
    print(STDERR "     : -t attributeName[:indextypes[:matchingrules]]\n");
    print(STDERR "                          - attribute: name of the attribute to be indexed\n");
    print(STDERR "                            If omitted, all the indexes defined \n");
    print(STDERR "                            for that instance are generated.\n");
    print(STDERR "                          - indextypes: comma separated index types\n");
    print(STDERR "                          - matchingrules: comma separated matrules\n");
    print(STDERR "                          Example: -t foo:eq,pres\n");
    print(STDERR "     : -v                 - verbose\n");
}

$instance = "";
$rootdn = "";
$passwd = "";
$passwdfile = "";
$attribute_arg = "";
$vlvattribute_arg = "";
$verbose = 0;

$prefix = "{{DS-ROOT}}";

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

$i = 0;
while ($i <= $#ARGV) 
{
    if ("$ARGV[$i]" eq "-n")
    {    
        # instance
        $i++; $instance = $ARGV[$i];
    }
    elsif ("$ARGV[$i]" eq "-D") 
    {    
        # Directory Manager
        $i++; $rootdn = $ARGV[$i];
    }
    elsif ("$ARGV[$i]" eq "-w") 
    {    
        # Directory Manager's password
        $i++; $passwd = $ARGV[$i];
    } 
    elsif ("$ARGV[$i]" eq "-j")
    {
         # Read Directory Manager's password from a file
        $i++; $passwdfile = $ARGV[$i];
    }
    elsif ("$ARGV[$i]" eq "-t") 
    {    
        # Attribute to index
        $i++; $attribute_arg = $ARGV[$i];
    }
    elsif ("$ARGV[$i]" eq "-T") 
    {    
        # Vlvattribute to index
        $i++; $vlvattribute_arg = $ARGV[$i];
    }
    elsif ("$ARGV[$i]" eq "-v") 
    {    
        # verbose
        $verbose = 1;
    }
    else
    {
        &usage; exit(1);
    }
    $i++;
}

if ($passwdfile ne ""){
# Open file and get the password
    unless (open (RPASS, $passwdfile)) {
        die "Error, cannot open password file $passwdfile\n";
    }
    $passwd = <RPASS>;
    chomp($passwd);
    close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
    die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
        "part of the standard perl distribution. If you want to use it, you must\n",
        "download and install the module. You can find it at\n",
        "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#    print "Bind Password: ";
#    ReadMode('noecho'); 
#    $passwd = ReadLine(0); 
#    chomp($passwd);
#    ReadMode('normal');
}

if ( $rootdn eq "" || $passwd eq "" ) 
{ 
    &usage; 
    exit(1); 
}

$vstr = "";
if ($verbose != 0) 
{ 
    $vstr = "-v"; 
}

($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "db2index_${yr}_${mn}_${dy}_${h}_${m}_${s}";

if ( $instance eq "" )
{
    &usage;
    exit(1);
}

# No attribute name has been specified: let's get them from the configuration
$attribute="";
$indexes_list="";
$vlvattribute="";
$vlvindexes_list="";
chdir("$prefix{{SEP}}usr{{SEP}}bin");
if ( $attribute_arg eq "" && $vlvattribute_arg eq "" )
{
    # Get the list of indexes from the entry
    $indexes_list="ldapsearch $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -s one " .
    "-b \"cn=index,cn=\"$instance\", cn=ldbm database,cn=plugins,cn=config\" \"(&(objectclass=*)(nsSystemIndex=false))\" cn";
    # build the values of the attribute nsIndexAttribute
    open(LDAP1, "$indexes_list |");
    while (<LDAP1>) {
        s/\n //g;
        if (/^cn: (.*)\n/) {
            $IndexAttribute="nsIndexAttribute";
            $attribute="$attribute$IndexAttribute: $1\n";
        }
    }
    close(LDAP1);
    if ( $attribute eq "" )
    {
        # No attribute to index, just exit
        exit(0);
    }

    # Get the list of indexes from the entry
    $vlvindexes_list="ldapsearch $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -s sub -b \"cn=\"$instance\", cn=ldbm database,cn=plugins,cn=config\" \"objectclass=vlvIndex\" cn";

    # build the values of the attribute nsIndexVlvAttribute
    open(LDAP1, "$vlvindexes_list |");
    while (<LDAP1>) {
        s/\n //g;
        if (/^cn: (.*)\n/) {
            $vlvIndexAttribute="nsIndexVlvAttribute";
            $vlvattribute="$vlvattribute$vlvIndexAttribute: $1\n";
        }
    }
    close(LDAP1);
}
else
{
    if ( $attribute_arg ne "" )
    {
        $attribute="nsIndexAttribute: $attribute_arg\n";
    }
    if ( $vlvattribute_arg ne "" )
    {
        $vlvattribute="nsIndexVlvAttribute: $vlvattribute_arg\n";
    }
}

# Build the task entry to add

$dn = "dn: cn=$taskname, cn=index, cn=tasks, cn=config\n";
$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
$cn =  "cn: $taskname\n";
$nsinstance = "nsInstance: ${instance}\n";

$entry = "${dn}${misc}${cn}${nsinstance}${attribute}${vlvattribute}";
open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
print(FOO "$entry");
close(FOO);


--- NEW FILE template-db2ldif.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub usage {
	print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
	print(STDERR "        {-n instance}* | {-s include}* [{-x exclude}*] \n");
	print(STDERR "        [-m] [-M] [-u] [-C] [-N] [-U] [-a filename]\n");
	print(STDERR " Opts: -D rootdn   - Directory Manager\n");
	print(STDERR "     : -w password - Directory Manager's password\n");
	print(STDERR "     : -w -        - Prompt for Directory Manager's password\n");
	print(STDERR "     : -j filename - Read Directory Manager's password from file\n");
	print(STDERR "     : -n instance - instance to be exported\n");
	print(STDERR "     : -a filename - output ldif file\n");
	print(STDERR "     : -s include  - included suffix(es)\n");
	print(STDERR "     : -x exclude  - excluded suffix(es)\n");
	print(STDERR "     : -m          - minimal base64 encoding\n");
	print(STDERR "     : -M          - output ldif is stored in multiple files\n");
	print(STDERR "                     these files are named : <instance>_<filename>\n");
	print(STDERR "                     by default, all instances are stored in <filename>\n");
	print(STDERR "     : -r          - export replica\n");
	print(STDERR "     : -u          - do not export unique id\n");
	print(STDERR "     : -C          - use main db file only\n");
	print(STDERR "     : -N          - suppress printing sequential number\n");
	print(STDERR "     : -U          - output ldif is not folded\n");
	print(STDERR "     : -E          - Decrypt encrypted data when exporting\n");
	print(STDERR "     : -1          - do not print version line\n");
	print(STDERR "     : -v          - verbose\n");
}

@instances = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
@included = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
@excluded = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
$maxidx = 50;
$nowrap = 0;
$nobase64 = 0;
$noversion = 0;
$nouniqueid = 0;
$useid2entry = 0;
$onefile = 1;
$printkey = 1;
$taskname = "";
$ldiffile = "";
$doreplica = 0;
$prefix = "{{DS-ROOT}}";
$ldifdir = "{{LDIF-DIR}}";
$servid = "{{SERV-ID}}";
$verbose = 0;
$rootdn = "";
$passwd = "";
$passwdfile = "";
$i = 0;
$insti = 0;
$incli = 0;
$excli = 0;
$decrypt_on_export = 0;
while ($i <= $#ARGV) {
	if ( "$ARGV[$i]" eq "-n" ) {	# instances
		$i++;
		if ($insti < $maxidx) {
			$instances[$insti] = $ARGV[$i]; $insti++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-s") {	# included suffix
		$i++;
		if ($incli < $maxidx) {
			$included[$incli] = $ARGV[$i]; $incli++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-x") {	# excluded suffix
		$i++;
		if ($excli < $maxidx) {
			$excluded[$excli] = $ARGV[$i]; $excli++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-a") {	# ldif file
		$i++; $ldiffile = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-D") {	# Directory Manager
		$i++; $rootdn = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-w") {	# Directory Manager's password
		$i++; $passwd = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-j") { # Read Directory Manager's password from a file
		$i++; $passwdfile = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-M") {	# multiple ldif file
		$onefile = 0;
	} elsif ("$ARGV[$i]" eq "-o") {	# one ldif file
		$onefile = 1;
	} elsif ("$ARGV[$i]" eq "-u") {	# no dump unique id
		$nouniqueid = 1;
	} elsif ("$ARGV[$i]" eq "-C") {	# use id2entry
		$useid2entry = 1;
	} elsif ("$ARGV[$i]" eq "-N") {	# does not print key
		$printkey = 0;
	} elsif ("$ARGV[$i]" eq "-r") {	# export replica
		$doreplica = 1;
	} elsif ("$ARGV[$i]" eq "-m") {	# no base64
		$nobase64 = 1;
	} elsif ("$ARGV[$i]" eq "-U") {	# no wrap
		$nowrap = 1;
	} elsif ("$ARGV[$i]" eq "-1") {	# no version line
		$noversion = 1;
	} elsif ("$ARGV[$i]" eq "-E") {	# decrypt
		$decrypt_on_export = 1;
	} elsif ("$ARGV[$i]" eq "-v") {	# verbose
		$verbose = 1;
	} else {
		&usage; exit(1);
	}
	$i++;
}
if ($passwdfile ne ""){
# Open file and get the password
	unless (open (RPASS, $passwdfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$passwd = <RPASS>;
	chomp($passwd);
	close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$passwd = ReadLine(0); 
#	chomp($passwd);
#	ReadMode('normal');
}
if (($instances[0] eq "" && $included[0] eq "") || $rootdn eq "" || $passwd eq "") { &usage; exit(1); }
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "export_${yr}_${mn}_${dy}_${h}_${m}_${s}";
if ($ldiffile eq "") {
	$ldiffile = "${ldifdir}{{SEP}}${servid}-${yr}_${mn}_${dy}_${h}_${m}_${s}.ldif";
}
$dn = "dn: cn=$taskname, cn=export, cn=tasks, cn=config\n";
$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
$cn =  "cn: $taskname\n";
$i = 0;
$nsinstance = "";
while ("" ne "$instances[$i]") {
	$nsinstance = "${nsinstance}nsInstance: $instances[$i]\n";
	$i++;
}
$i = 0;
$nsincluded = "";
while ("" ne "$included[$i]") {
	$nsincluded = "${nsincluded}nsIncludeSuffix: $included[$i]\n";
	$i++;
}
$i = 0;
$nsexcluded = "";
while ("" ne "$excluded[$i]") {
	$nsexcluded = "${nsexcluded}nsExcludeSuffix: $excluded[$i]\n";
	$i++;
}
$nsreplica = "";
if ($doreplica != 0) { $nsreplica = "nsExportReplica: true\n"; }
$nsnobase64 = "";
if ($nobase64 != 0) { $nsnobase64 = "nsMinimalEncoding: true\n"; }
$nsnowrap = "";
if ($nowrap != 0) { $nsnowrap = "nsNoWrap: true\n"; }
$nsnoversion = "";
if ($noversion != 0) { $nsnoversion = "nsNoVersionLine: true\n"; }
$nsnouniqueid = "";
if ($nouniqueid != 0) { $nsnouniqueid = "nsDumpUniqId: false\n"; }
$nsuseid2entry = "";
if ($useid2entry != 0) { $nsuseid2entry = "nsUseId2Entry: true\n"; }
$nsonefile = "";
if ($onefile != 0) { $nsonefile = "nsUseOneFile: true\n"; }
if ($onefile == 0) { $nsonefile = "nsUseOneFile: false\n"; }
$nsexportdecrypt = "";
if ($decrypt_on_export != 0) { $nsexportdecrypt = "nsExportDecrypt: true\n"; }
$nsprintkey = "";
if ($printkey == 0) { $nsprintkey = "nsPrintKey: false\n"; }
$nsldiffile = "nsFilename: ${ldiffile}\n";
$entry = "${dn}${misc}${cn}${nsinstance}${nsincluded}${nsexcluded}${nsreplica}${nsnobase64}${nsnowrap}${nsnoversion}${nsnouniqueid}${nsuseid2entry}${nsonefile}${nsexportdecrypt}${nsprintkey}${nsldiffile}";
$vstr = "";
if ($verbose != 0) { $vstr = "-v"; }
$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
print(FOO "$entry");
close(FOO);


--- NEW FILE template-ldif2db.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub usage {
	print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } \n");
	print(STDERR "        -n instance | {-s include}* [{-x exclude}*] [-O] [-c]\n");
	print(STDERR "        [-g [string]] [-G namespace_id] {-i filename}*\n");
	print(STDERR " Opts: -D rootdn     - Directory Manager\n");
	print(STDERR "     : -w password   - Directory Manager's password\n");
	print(STDERR "     : -w -          - Prompt for Directory Manager's password\n");
	print(STDERR "     : -j filename   - Read Directory Manager's password from file\n");
	print(STDERR "     : -n instance   - instance to be imported to\n");
	print(STDERR "     : -i filename   - input ldif file(s)\n");
	print(STDERR "     : -s include    - included suffix\n");
	print(STDERR "     : -x exclude    - excluded suffix(es)\n");
	print(STDERR "     : -O            - only create core db, no attr indexes\n");
	print(STDERR "     : -c size       - merge chunk size\n");
	print(STDERR "     : -g [string]   - string is \"none\" or \"deterministic\"\n");
	print(STDERR "     :          none - unique id is not generated\n");
	print(STDERR "     : deterministic - generate name based unique id (-G name)\n");
	print(STDERR "     :    by default - generate time based unique id\n");
	print(STDERR "     : -G name       - namespace id for name based uniqueid (-g deterministic)\n");
	print(STDERR "     : -E            - Encrypt data when importing\n");
	print(STDERR "     : -v            - verbose\n");
}

@ldiffiles = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
@included = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
@excluded = (
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	"", "", "", "", "", "", "", "", "", "",
	""
);
$maxidx = 50;
$instance = "";
$noattrindexes = 0;
$mergechunksiz = 0;
$genuniqid = "time";
$uniqidname = "";
$taskname = "";
$prefix = "{{DS-ROOT}}";
$verbose = 0;
$rootdn = "";
$passwd = "";
$passwdfile = "";
$i = 0;
$ldifi = 0;
$incli = 0;
$excli = 0;
$encrypt_on_import = 0;
while ($i <= $#ARGV) {
	if ( "$ARGV[$i]" eq "-i" ) {	# ldiffiles
		$i++;
		if ($ldifi < $maxidx) {
			$ldiffiles[$ldifi] = $ARGV[$i]; $ldifi++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-s") {	# included suffix
		$i++;
		if ($incli < $maxidx) {
			$included[$incli] = $ARGV[$i]; $incli++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-x") {	# excluded suffix
		$i++;
		if ($excli < $maxidx) {
			$excluded[$excli] = $ARGV[$i]; $excli++;
		} else {
			&usage; exit(1);
		}
	} elsif ("$ARGV[$i]" eq "-n") {	# instance
		$i++; $instance = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-D") {	# Directory Manager
		$i++; $rootdn = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-w") {	# Directory Manager's password
		$i++; $passwd = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-j") { # Read Directory Manager's password from a file
		$i++; $passwdfile = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-O") {	# no attr indexes
		$noattrindexes = 1;
	} elsif ("$ARGV[$i]" eq "-c") {	# merge chunk size
		$i++; $mergechunksiz = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-g") {	# generate uniqueid
		if (("$ARGV[$i+1]" ne "") && !("$ARGV[$i+1]" =~ /^-/)) {
			$i++;
			if ("$ARGV[$i]" eq "none") {
				$genuniqid = $ARGV[$i];
			} elsif ("$ARGV[$i]" eq "deterministic") {
				$genuniqid = $ARGV[$i];
			}
		}
	} elsif ("$ARGV[$i]" eq "-G") {	# namespace id
		$i++; $uniqidname = $ARGV[$i];
	} elsif ("$ARGV[$i]" eq "-v") {	# verbose
		$verbose = 1;
	} elsif ("$ARGV[$i]" eq "-E") {	# encrypt on import
		$encrypt_on_import = 1;
	} else {
		&usage; exit(1);
	}
	$i++;
}
if ($passwdfile ne ""){
# Open file and get the password
	unless (open (RPASS, $passwdfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$passwd = <RPASS>;
	chomp($passwd);
	close(RPASS);
} elsif ($passwd eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$passwd = ReadLine(0); 
#	chomp($passwd);
#	ReadMode('normal');
}
if (($instance eq "" && $included[0] eq "") || $ldiffiles[0] eq "" || $rootdn eq "" || $passwd eq "") { &usage; exit(1); }
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "import_${yr}_${mn}_${dy}_${h}_${m}_${s}";
$dn = "dn: cn=$taskname, cn=import, cn=tasks, cn=config\n";
$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
$cn =  "cn: $taskname\n";
if ($instance ne "") {
	$nsinstance = "nsInstance: ${instance}\n";
}
$i = 0;
$nsldiffiles = "";
while ("" ne "$ldiffiles[$i]") {
	$nsldiffiles = "${nsldiffiles}nsFilename: $ldiffiles[$i]\n";
	$i++;
}
$i = 0;
$nsincluded = "";
while ("" ne "$included[$i]") {
	$nsincluded = "${nsincluded}nsIncludeSuffix: $included[$i]\n";
	$i++;
}
$i = 0;
$nsexcluded = "";
while ("" ne "$excluded[$i]") {
	$nsexcluded = "${nsexcluded}nsExcludeSuffix: $excluded[$i]\n";
	$i++;
}
$nsnoattrindexes = "";
if ($noattrindexes != 0) { $nsnoattrindexes = "nsImportIndexAttrs: false\n"; }
$nsimportencrypt = "";
if ($encrypt_on_import != 0) { $nsimportencrypt = "nsImportEncrypt: true\n"; }
$nsmergechunksiz = "nsImportChunkSize: ${mergechunksiz}\n"; 
$nsgenuniqid = "nsUniqueIdGenerator: ${genuniqid}\n"; 
$nsuniqidname = "";
if ($uniqidname ne "") { $nsuniqidname = "nsUniqueIdGeneratorNamespace: ${uniqidname}\n"; }
$entry = "${dn}${misc}${cn}${nsinstance}${nsincluded}${nsexcluded}${nsldiffiles}${nsnoattrindexes}${nsimportencrypt}${nsmergechunksiz}${nsgenuniqid}${nsuniqidname}";
$vstr = "";
if ($verbose != 0) { $vstr = "-v"; }
$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
print(FOO "$entry");
close(FOO);


--- NEW FILE template-ns-accountstatus.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

###############################
# SUB-ROUTINES
###############################

sub usage_and_exit
{
	print (STDERR "$cmd [-D rootdn] { -w password | -w - | -j filename } \n");
	print (STDERR "     [-p port] [-h host] -I DN-to-$operation\n\n");
	print (STDERR "May be used to $operation a user or a domain of users\n\n");
	print (STDERR "Arguments:\n");
	print (STDERR "          -?                   - help\n");
	print (STDERR "          -D rootdn            - Provide a Directory Manager DN. Default= '$defrootdn'\n");
	print (STDERR "          -w password          - Provide a password for the Directory Manager DN\n");
	print (STDERR "          -w -                 - Prompt for the Directory Manager's password\n");
	print (STDERR "          -j filename          - Read the Directory Manager's password from file\n");
	print (STDERR "          -p port              - Provide a port. Default= '$defport'\n");
	print (STDERR "          -h host              - Provide a host name. Default= '$defhost'\n");
	print (STDERR "          -I DN-to-$operation  - Single entry DN or role DN to $operation\n");
	exit 100;
}

sub debug
{
#	print " ==> @_";
}

sub out
{
	print "@_";
}

# --------------------------
# Check if the entry is part of a locked role:
# i.e.: for each role member (nsroledn) of nsdisabledrole, check if
# 	* it is the same as the entry
# 	* the entry is member of role (==has nsroledn attributes), compare each of
#		them with the nsroledn of nsdisabledrole
#	* if nsroledn of nsdisabledrole are complex, go through each of them
# argv[0] is the local file handler
# argv[1] is the entry (may be a single entry DN or a role DN)
# argv[2] is the base for the search
# --------------------------

$throughRole="";

sub indirectLock
{
	# For recursivity, file handler must be local
	my $L_filehandle=$_[0];
	$L_filehandle++;

	my $L_entry=$_[1];
	# Remove useless space
    my @L_intern=split /([,])/,$L_entry;
    my $L_result="";
    foreach $L_part (@L_intern)
    {
        $L_part=~s/^ +//;
        $L_part=~ tr/A-Z/a-z/;
        $L_result="$L_result$L_part";
    }
    $L_entry=$L_result;

	my $L_base=$_[2];
	
	my $L_search;
	my $L_currentrole;
	my $L_retCode;

	my $L_local;

`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn >> {{DEV-NULL}} 2>&1 `;
$retCode=$?;
if ( $retCode != 0 )
{
    $retCode=$?>>8;
    return 1;
}

	# Check if the role is a nested role
	@L_Nested="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=nsNestedRoleDefinition)(objectclass=ldapsubentry))\"  ";
	# L_isNested == 1 means that we are going through a nested role, so for each member of that
	# nested role, check that the member is below the scope of the nested
	$L_isNested=@L_Nested;

	# Not Direct Lock, Go through roles if any
	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn ";

	debug("\t-->indirectLock: check if $L_entry is part of a locked role from base $L_base\n\n");

	unless (open ($L_filehandle, "$L_search |")) 
	{
		out("Can't open file $L_filehandle\n");
		exit;
	}
	while (<$L_filehandle>) {

		s/\n //g;
		if (/^nsroledn: (.*)\n/) {
			$L_currentrole = $1;

			# Remove useless space
			my @L_intern=split /([,])/,$L_currentrole;
			my $L_result="";
			foreach $L_part (@L_intern)
			{
				$L_part=~s/^ +//;
				$L_part=~ tr/A-Z/a-z/;
				$L_result="$L_result$L_part";
			}
			$L_currentrole=$L_result;

			debug("\t-- indirectLock loop: current nsroledn $L_currentrole of base $L_base\n");
			if ( $L_isNested == 1 )
			{
				if ( checkScope($L_currentrole, $L_base) == 0 )
				{
					# Scope problem probably a bad conf, skip the currentrole
					next;	
				}
			}

			if ( $L_currentrole eq $L_entry )
			{
				# the entry is a role that is directly locked
				# i.e, nsroledn of nsdisabledrole contains the entry
				$throughRole=$L_base;
				$throughRole=~ tr/A-Z/a-z/;

				# skipDisabled means that we've just found that the entry (which is a role)
				# is locked directly (==its DN is part of nsroledn attributes)
				# we just want to know now, if it is locked through another role
				# at least, one
				if ( $skipDisabled == 1 )
				{
					# direct inactivation
					$directLocked=1;
					# just go through that test once
					$skipDisabled=0;
					next;
				}
				debug("\t-- 1 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			$L_retCode=memberOf($L_currentrole, $L_entry);
			if ( $L_retCode == 0 && $single == 1 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				if ( $skipManaged == 1 )
				{
					if ( $L_currentrole eq $nsManagedDisabledRole)
					{
						# Try next nsroledn
						$directLocked=1;
						$skipManaged=0;
						next;
					}
				} 
				debug("\t-- 2 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			# Only for the first iteration
			# the first iteration is with nsdisabledrole as base, other
			# loops are deeper
			$L_local=$skipDisabled;
			$skipDisabled=0;
	
			# the current nsroledn may be a complex role, just go through
			# its won nsroledn
			$L_retCode=indirectLock($L_filehandle,$L_entry, $L_currentrole);

			# Because of recursivity, to keep the initial value for the first level
			$skipDisabled=$L_local;

			if ( $L_retCode == 0 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				debug("\t-- 3 indirectLock: $L_entry locked throughRole == $throughRole\n");
				return 0;
			}
		}
	}

	close($L_filehandle);

	debug("\t<--indirectLock: no more nsroledn to process\n");
	return 1;
}

# --------------------------
# Check if nsroledn is part of the entry attributes
# argv[0] is a role DN (nsroledn attribute)
# argv[1] is the entry
# --------------------------
sub memberOf
{
	my $L_nsroledn=$_[0];
	$L_nsroledn=~ tr/A-Z/a-z/;

	my $L_entry=$_[1];

	my $L_search;
	my $L_currentrole;

	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_entry\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsrole";

	debug("\t\t-->memberOf: $L_search: check if $L_entry has $L_nsroledn as nsroledn attribute\n");

	open (LDAP2, "$L_search |");
	while (<LDAP2>) {
		s/\n //g;
		if (/^nsrole: (.*)\n/) {
			$L_currentrole = $1;
			$L_currentrole=~ tr/A-Z/a-z/;
			if ( $L_currentrole eq $L_nsroledn )
			{
				# the parm is part of the $L_entry nsroledn
				debug("\t\t<--memberOf: $L_entry locked through $L_nsroledn\n");
				return 0;
			}
		}
	}
	close(LDAP2);

	# the parm is not part of the $L_entry nsroledn
	debug("\t\t<--memberOf: $L_entry not locked through $L_nsroledn\n");
	return 1;
}


# --------------------------
# Remove the rdn of a DN
# argv[0] is a DN
# --------------------------
sub removeRdn
{
    $L_entry=$_[0];

    @L_entryToTest=split /([,])/,$L_entry;
    debug("removeRdn: entry to split: $L_entry**@L_entryToTest\n");

    $newDN="";
    $removeRDN=1;
    foreach $part (@L_entryToTest)
    {
        $part=~ s/^ +//;
        $part=~ tr/A-Z/a-z/;
        if ( $removeRDN <= 2 )
        {
            $removeRDN=$removeRDN+1;
        }
        else
        {
            $newDN="$newDN$part";
        }
    }

    debug("removeRdn: new DN **$newDN**\n");
}

# --------------------------
# Check if L_current is below the scope of 
# L_nestedRole
# argv[0] is a role
# argv[1] is the nested role
# --------------------------
sub checkScope
{
    $L_current=$_[0];
    $L_nestedRole=$_[1];

    debug("checkScope: check if $L_current is below $L_nestedRole\n");

    removeRdn($L_nestedRole);
    $L_nestedRoleSuffix=$newDN;
    debug("checkScope: nested role based:  $L_nestedRoleSuffix\n");

    $cont=1;
    while ( ($cont == 1) && ($L_current ne "") )
    {
        removeRdn($L_current);
        $currentDn=$newDN;
        debug("checkScope: current DN to check: $currentDn\n");
 
        if ( $currentDn eq $L_nestedRoleSuffix )
        {
            debug("checkScope: DN match!!!\n");
            $cont = 0;
        }
        else
        {
            $L_current=$currentDn;
        }
    }
 
    if ( $cont == 1 )
    {
        debug("checkScope: $_[0] and $_[1] are not compatible\n");
        return 0;
    }
    else
    {
        debug("checkScope: $_[0] and $_[1] are compatible\n");
        return 1;
    }
}


###############################
# MAIN ROUTINE
###############################

# Generated variable
$prefix="{{DS-ROOT}}";

# Determine which command we are running
if ( $0 =~ /ns-inactivate(.pl)?$/ )
{
	$cmd="ns-inactivate.pl";
	$operation="inactivate";
	$state="inactivated";
	$modrole="add";
	$already="already";
}
elsif ( $0 =~ /ns-activate(.pl)?$/ )
{
	$cmd="ns-activate.pl";
	$operation="activate";
	$state="activated";
	$modrole="delete";
	$already="already";
}
elsif ( $0 =~ /ns-accountstatus(.pl)?$/ )
{
	$cmd="ns-accountstatus.pl";
	$operation="get status of";
	$state="activated";
	# no need for $modrole as no operation is performed
	$already="";

}
else
{
	out("$0: unknown command\n");
	exit 100;
}

debug("Running ** $cmd ** $operation\n");

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

$ldapsearch="ldapsearch -1";
$ldapmodify="ldapmodify";
 
# Default values
$defrootdn= "{{ROOT-DN}}";
$defhost= "{{SERVER-NAME}}";
$defport= "{{SERVER-PORT}}";

# User values
$rootdn= "{{ROOT-DN}}";
$rootpw= "";
$pwfile= "";
$host= "{{SERVER-NAME}}";
$port= "{{SERVER-PORT}}";
$entry= "";

$single=0;
$role=0;

# Process the command line arguments
while( $arg = shift)
{
    if($arg eq "-?")
    {
        usage_and_exit();
    }
    elsif($arg eq "-D")
    {
        $rootdn= shift @ARGV;
    }
    elsif($arg eq "-w")
    {
        $rootpw= shift @ARGV;
    }
    elsif($arg eq "-j")
    {
        $pwfile= shift @ARGV;
    }
    elsif($arg eq "-p")
    {
        $port= shift @ARGV;
    }
    elsif($arg eq "-h")
    {
        $host= shift @ARGV;
    }
    elsif($arg eq "-I")
    {
        $entry= shift @ARGV;
    }
	else
	{
		print "$arg: Unknown command line argument.\n";
		usage_and_exit();
	}
}

if ($pwfile ne ""){
# Open file and get the password
	unless (open (RPASS, $pwfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$rootpw = <RPASS>;
	chomp($rootpw);
	close(RPASS);
} elsif ($rootpw eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$rootpw = ReadLine(0); 
#	chomp($rootpw);
#	ReadMode('normal');
}

if( $rootpw eq "" )
{
	usage_and_exit();
}

if( $entry eq "" )
{
	usage_and_exit();
}

#
# Check the actual existence of the entry to inactivate/activate
# and at the same time, validate the various parm: port, host, rootdn, rootpw
#
@exist=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" dn`;
$retCode1=$?;
if ( $retCode1 != 0 )
{
	$retCode1=$?>>8;
	exit $retCode1;
}

@isRole=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(&(objectclass=LDAPsubentry)(objectclass=nsRoleDefinition))\" dn`;
$nbLineRole=@isRole;
$retCode2=$?;
if ( $retCode2 != 0 )
{
	$retCode2=$?>>8;
	exit $retCode2;
}

if ( $nbLineRole == 1 )
{
	debug("Groups of users\n");
	$role=1;
}
else
{
	debug("Single user\n");
	$single=1;
}

#
# First of all, check the existence of the nsaccountlock attribute in the entry
#
$isLocked=0;
if ( $single == 1 )
{
	$searchAccountLock="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" nsaccountlock";
	open (LDAP1, "$searchAccountLock |");
	while (<LDAP1>) {
		s/\n //g;
		if (/^nsaccountlock: (.*)\n/) {
			$L_currentvalue = $1;
			$L_currentvalue=~ tr/A-Z/a-z/;
			if ( $L_currentvalue eq "true")
			{
				$isLocked=1;
			}
			elsif ( $L_currentvalue eq "false" )
			{
				$isLocked=0;
			}
		}
	}
	close(LDAP1);
}
debug("Is the entry already locked? ==> $isLocked\n");

#
# Get the suffix name of that entry
#

# Remove the space at the beginning (just in case...)
#	-I "uid=jvedder , ou=People , o=sun.com"
@suffix=split /([,])/,$entry;
$result="";
foreach $part (@suffix)
{
	$part=~s/^ +//;
	$part=~ tr/A-Z/a-z/;
	$result="$result$part";
}
@suffixN=$result;

debug("Entry to $operation: #@suffix#\n");
debug("Entry to $operation: #@suffixN#\n");

# Get the suffix
$cont=0;
while ($cont == 0)
{
	# Look if suffix is the suffix of the entry
	#	ldapsearch -s one -b "cn=mapping tree,cn=config" "cn=\"uid=jvedder,ou=People,o=sun.com\""
	#
	debug("\tSuffix from the entry: #@suffixN#\n");
	@mapping=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s one -b \"cn=mapping tree, cn=config\" \"cn=\\"@suffixN\\"\" cn `;

	$retCode=$?;
	if ( $retCode != 0 )
	{
		$retCode=$?>>8;
		exit $retCode;
	}

	# If we get a result, remove the dn:
	#	dn: cn="o=sun.com",cn=mapping tree,cn=config
	#	cn: "o=sun.com"
	#
	shift @mapping;

	foreach $res (@mapping)
	{
		# Break the string cn: "o=sun.com" into pieces
		@cn= split(/ /,$res);

		# And remove the cn: part
		shift @cn;

		# Now compare the suffix we extract from the mapping tree 
		# with the suffix derived from the entry
		debug("\tSuffix from mapping tree: #@cn#\n");
		if ( @cn eq @suffixN ) {
			debug("Found matching suffix\n");
			$cont=1;
		}
	}

	if ( $cont == 0 )
	{
		# Remove the current rdn to try another suffix
		shift @suffix;

		$result="";
		foreach $part (@suffix)
		{
			$part=~ s/^ +//;
			$part=~ tr/A-Z/a-z/;
			$result="$result$part";
		}
		@suffixN=$result;

		debug("\t\tNothing found => go up one level in rdn #@suffix#\n");
		$len=@suffix;
		if ( $len == 0 )
		{
			debug("Can not find suffix. Problem\n");
			$cont=2;
		}
	}
}
if ( $cont == 2)
{
	out("Can not find suffix for entry $entry\n");
	exit 100;
}

if ( $operation eq "inactivate" )
{
	#
	# Now that we have the suffix and we know if we deal with a single entry or
	# a role, just try to create the COS and roles associated.
	#
	@base=(
		"cn=nsManagedDisabledRole, at suffixN",
		"cn=nsDisabledRole, at suffixN",
		"cn=nsAccountInactivationTmp, at suffixN",
		"\'cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\'",
		"cn=nsAccountInactivation_cos, at suffixN" );

	$addrolescos="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c -a >> {{DEV-NULL}} 2>&1 ";
	@role1=(
		"dn: cn=nsManagedDisabledRole, at suffixN\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsSimpleRoleDefinition\n",
		"objectclass: nsManagedRoleDefinition\n",
		"cn: nsManagedDisabledRole\n\n" );
	@role2=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsComplexRoleDefinition\n",
		"objectclass: nsNestedRoleDefinition\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n",
		"cn: nsDisabledRole\n\n" );
	@cos1=(
		"dn: cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: nsContainer\n\n" );
	@cos2=(
		"dn: cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: extensibleObject\n",
		"objectclass: costemplate\n",
		"objectclass: ldapsubentry\n",
		"cosPriority: 1\n",
		"nsAccountLock: true\n\n" );
	@cos3=(
		"dn: cn=nsAccountInactivation_cos, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: cosSuperDefinition\n",
		"objectclass: cosClassicDefinition\n",
		"cosTemplateDn: cn=nsAccountInactivationTmp, at suffixN\n",
		"cosSpecifier: nsRole\n",
		"cosAttribute: nsAccountLock operational\n\n" );

	@all=(\@role1, \@role2, \@cos1, \@cos2, \@cos3);

	$i=0;

	foreach $current (@base)
	{
		debug("Creating $current ??\n");
		open(FD,"| $addrolescos ");
		print FD @{$all[$i]};
		close(FD);
		if ( $? != 0 )
		{
			$retCode=$?>>8;
			if ( $retCode == 68 )
			{
				debug("Entry $current already exists, ignore error\n");
			}
			else
			{
				# Probably a more serious problem.
				# Exit with LDAP error
				exit $retCode;
			}
		}
		else
		{
			debug("Entry $current created\n");
		}
		$i=$i+1;
	}
}

$skipManaged=0;
$skipDisabled=0;
$directLocked=0;

$nsDisabledRole="cn=nsDisabledRole, at suffixN";
$nsDisabledRole=~ tr/A-Z/a-z/;

$nsManagedDisabledRole="cn=nsManagedDisabledRole, at suffixN";
$nsManagedDisabledRole=~ tr/A-Z/a-z/;

if ( $operation eq "inactivate" )
{
	# Go through all the roles part of nsdisabledrole to check if the entry
	# is a member of one of those roles
	$ret=indirectLock("LDAP00", $entry, $nsDisabledRole);
	if ( $ret == 0 )
	{
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			# indirect lock
			out("$entry already $state through $throughRole.\n");
		}
		else
		{
			# direct lock
			out("$entry already $state.\n");
		}
		exit 100;
	}
	elsif ( $isLocked == 1 )
	{
		# the entry is not locked through a role, may be nsaccountlock is "hardcoded" ?
		out("$entry already $state (probably directly).\n");
		exit 103;
	}
}
elsif ( $operation eq "activate" || $operation eq "get status of" )
{
	$skipManaged=$single;
	$skipDisabled=$role;

	$ret=indirectLock("LDAP00",$entry, $nsDisabledRole);

	if ( $ret == 0 )
	{
		# undirectly locked
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			if ( $operation eq "activate" )
			{
				out("$entry inactivated through $throughRole. Can not activate it individually.\n");
				exit 100;
			}
			else
			{
				out("$entry inactivated through $throughRole.\n");
				exit 104;
			}
		}
		debug("$entry locked individually\n");

		if ( $operation ne "activate" )
		{
			out("$entry inactivated.\n");
			exit 103;
		}
	}
	elsif ( $directLocked == 0 )
	{
		if ( $operation eq "activate" && $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 100;
		}
		elsif ( $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 102;
		}
		else
		{
			# not locked using our schema, but nsaccountlock is probably present
			out("$entry inactivated (probably directly).\n");
			exit 103;
		}
	}
	elsif ( $operation ne "activate" )
	{
		out("$entry inactivated.\n");
		exit 103;
	}
	# else Locked directly, juste unlock it!
	debug("$entry locked individually\n");
}

#
# Inactivate/activate the entry
#
$action="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c >> {{DEV-NULL}} 2>&1";
if ( $single == 1 )
{
	@record=(
		"dn: $entry\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n\n" );
}
else
{
	@record=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: $entry\n\n" );
}
open(FD,"| $action ");
print FD @record;
close(FD);
if ( $? != 0 )
{
debug("$modrole, $entry\n");
	$retCode=$?>>8;
	exit $retCode;
}

out("$entry $state.\n");
exit 0;


--- NEW FILE template-ns-activate.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

###############################
# SUB-ROUTINES
###############################

sub usage_and_exit
{
	print (STDERR "$cmd [-D rootdn] { -w password | -w - | -j filename } \n");
	print (STDERR "     [-p port] [-h host] -I DN-to-$operation\n\n");
	print (STDERR "May be used to $operation a user or a domain of users\n\n");
	print (STDERR "Arguments:\n");
	print (STDERR "          -?                   - help\n");
	print (STDERR "          -D rootdn            - Provide a Directory Manager DN. Default= '$defrootdn'\n");
	print (STDERR "          -w password          - Provide a password for the Directory Manager DN\n");
	print (STDERR "          -w -                 - Prompt for the Directory Manager's password\n");
	print (STDERR "          -j filename          - Read the Directory Manager's password from file\n");
	print (STDERR "          -p port              - Provide a port. Default= '$defport'\n");
	print (STDERR "          -h host              - Provide a host name. Default= '$defhost'\n");
	print (STDERR "          -I DN-to-$operation  - Single entry DN or role DN to $operation\n");
	exit 100;
}

sub debug
{
#	print " ==> @_";
}

sub out
{
	print "@_";
}

# --------------------------
# Check if the entry is part of a locked role:
# i.e.: for each role member (nsroledn) of nsdisabledrole, check if
# 	* it is the same as the entry
# 	* the entry is member of role (==has nsroledn attributes), compare each of
#		them with the nsroledn of nsdisabledrole
#	* if nsroledn of nsdisabledrole are complex, go through each of them
# argv[0] is the local file handler
# argv[1] is the entry (may be a single entry DN or a role DN)
# argv[2] is the base for the search
# --------------------------

$throughRole="";

sub indirectLock
{
	# For recursivity, file handler must be local
	my $L_filehandle=$_[0];
	$L_filehandle++;

	my $L_entry=$_[1];
	# Remove useless space
    my @L_intern=split /([,])/,$L_entry;
    my $L_result="";
    foreach $L_part (@L_intern)
    {
        $L_part=~s/^ +//;
        $L_part=~ tr/A-Z/a-z/;
        $L_result="$L_result$L_part";
    }
    $L_entry=$L_result;

	my $L_base=$_[2];
	
	my $L_search;
	my $L_currentrole;
	my $L_retCode;

	my $L_local;

`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn >> {{DEV-NULL}} 2>&1 `;
$retCode=$?;
if ( $retCode != 0 )
{
    $retCode=$?>>8;
    return 1;
}

	# Check if the role is a nested role
	@L_Nested="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=nsNestedRoleDefinition)(objectclass=ldapsubentry))\"  ";
	# L_isNested == 1 means that we are going through a nested role, so for each member of that
	# nested role, check that the member is below the scope of the nested
	$L_isNested=@L_Nested;

	# Not Direct Lock, Go through roles if any
	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn ";

	debug("\t-->indirectLock: check if $L_entry is part of a locked role from base $L_base\n\n");

	unless (open ($L_filehandle, "$L_search |")) 
	{
		out("Can't open file $L_filehandle\n");
		exit;
	}
	while (<$L_filehandle>) {

		s/\n //g;
		if (/^nsroledn: (.*)\n/) {
			$L_currentrole = $1;

			# Remove useless space
			my @L_intern=split /([,])/,$L_currentrole;
			my $L_result="";
			foreach $L_part (@L_intern)
			{
				$L_part=~s/^ +//;
				$L_part=~ tr/A-Z/a-z/;
				$L_result="$L_result$L_part";
			}
			$L_currentrole=$L_result;

			debug("\t-- indirectLock loop: current nsroledn $L_currentrole of base $L_base\n");
			if ( $L_isNested == 1 )
			{
				if ( checkScope($L_currentrole, $L_base) == 0 )
				{
					# Scope problem probably a bad conf, skip the currentrole
					next;	
				}
			}

			if ( $L_currentrole eq $L_entry )
			{
				# the entry is a role that is directly locked
				# i.e, nsroledn of nsdisabledrole contains the entry
				$throughRole=$L_base;
				$throughRole=~ tr/A-Z/a-z/;

				# skipDisabled means that we've just found that the entry (which is a role)
				# is locked directly (==its DN is part of nsroledn attributes)
				# we just want to know now, if it is locked through another role
				# at least, one
				if ( $skipDisabled == 1 )
				{
					# direct inactivation
					$directLocked=1;
					# just go through that test once
					$skipDisabled=0;
					next;
				}
				debug("\t-- 1 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			$L_retCode=memberOf($L_currentrole, $L_entry);
			if ( $L_retCode == 0 && $single == 1 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				if ( $skipManaged == 1 )
				{
					if ( $L_currentrole eq $nsManagedDisabledRole)
					{
						# Try next nsroledn
						$directLocked=1;
						$skipManaged=0;
						next;
					}
				} 
				debug("\t-- 2 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			# Only for the first iteration
			# the first iteration is with nsdisabledrole as base, other
			# loops are deeper
			$L_local=$skipDisabled;
			$skipDisabled=0;
	
			# the current nsroledn may be a complex role, just go through
			# its won nsroledn
			$L_retCode=indirectLock($L_filehandle,$L_entry, $L_currentrole);

			# Because of recursivity, to keep the initial value for the first level
			$skipDisabled=$L_local;

			if ( $L_retCode == 0 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				debug("\t-- 3 indirectLock: $L_entry locked throughRole == $throughRole\n");
				return 0;
			}
		}
	}

	close($L_filehandle);

	debug("\t<--indirectLock: no more nsroledn to process\n");
	return 1;
}

# --------------------------
# Check if nsroledn is part of the entry attributes
# argv[0] is a role DN (nsroledn attribute)
# argv[1] is the entry
# --------------------------
sub memberOf
{
	my $L_nsroledn=$_[0];
	$L_nsroledn=~ tr/A-Z/a-z/;

	my $L_entry=$_[1];

	my $L_search;
	my $L_currentrole;

	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_entry\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsrole";

	debug("\t\t-->memberOf: $L_search: check if $L_entry has $L_nsroledn as nsroledn attribute\n");

	open (LDAP2, "$L_search |");
	while (<LDAP2>) {
		s/\n //g;
		if (/^nsrole: (.*)\n/) {
			$L_currentrole = $1;
			$L_currentrole=~ tr/A-Z/a-z/;
			if ( $L_currentrole eq $L_nsroledn )
			{
				# the parm is part of the $L_entry nsroledn
				debug("\t\t<--memberOf: $L_entry locked through $L_nsroledn\n");
				return 0;
			}
		}
	}
	close(LDAP2);

	# the parm is not part of the $L_entry nsroledn
	debug("\t\t<--memberOf: $L_entry not locked through $L_nsroledn\n");
	return 1;
}


# --------------------------
# Remove the rdn of a DN
# argv[0] is a DN
# --------------------------
sub removeRdn
{
    $L_entry=$_[0];

    @L_entryToTest=split /([,])/,$L_entry;
    debug("removeRdn: entry to split: $L_entry**@L_entryToTest\n");

    $newDN="";
    $removeRDN=1;
    foreach $part (@L_entryToTest)
    {
        $part=~ s/^ +//;
        $part=~ tr/A-Z/a-z/;
        if ( $removeRDN <= 2 )
        {
            $removeRDN=$removeRDN+1;
        }
        else
        {
            $newDN="$newDN$part";
        }
    }

    debug("removeRdn: new DN **$newDN**\n");
}

# --------------------------
# Check if L_current is below the scope of 
# L_nestedRole
# argv[0] is a role
# argv[1] is the nested role
# --------------------------
sub checkScope
{
    $L_current=$_[0];
    $L_nestedRole=$_[1];

    debug("checkScope: check if $L_current is below $L_nestedRole\n");

    removeRdn($L_nestedRole);
    $L_nestedRoleSuffix=$newDN;
    debug("checkScope: nested role based:  $L_nestedRoleSuffix\n");

    $cont=1;
    while ( ($cont == 1) && ($L_current ne "") )
    {
        removeRdn($L_current);
        $currentDn=$newDN;
        debug("checkScope: current DN to check: $currentDn\n");
 
        if ( $currentDn eq $L_nestedRoleSuffix )
        {
            debug("checkScope: DN match!!!\n");
            $cont = 0;
        }
        else
        {
            $L_current=$currentDn;
        }
    }
 
    if ( $cont == 1 )
    {
        debug("checkScope: $_[0] and $_[1] are not compatible\n");
        return 0;
    }
    else
    {
        debug("checkScope: $_[0] and $_[1] are compatible\n");
        return 1;
    }
}


###############################
# MAIN ROUTINE
###############################

# Generated variable
$prefix="{{DS-ROOT}}";

# Determine which command we are running
if ( $0 =~ /ns-inactivate(.pl)?$/ )
{
	$cmd="ns-inactivate.pl";
	$operation="inactivate";
	$state="inactivated";
	$modrole="add";
	$already="already";
}
elsif ( $0 =~ /ns-activate(.pl)?$/ )
{
	$cmd="ns-activate.pl";
	$operation="activate";
	$state="activated";
	$modrole="delete";
	$already="already";
}
elsif ( $0 =~ /ns-accountstatus(.pl)?$/ )
{
	$cmd="ns-accountstatus.pl";
	$operation="get status of";
	$state="activated";
	# no need for $modrole as no operation is performed
	$already="";

}
else
{
	out("$0: unknown command\n");
	exit 100;
}

debug("Running ** $cmd ** $operation\n");

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

$ldapsearch="ldapsearch -1";
$ldapmodify="ldapmodify";
 
# Default values
$defrootdn= "{{ROOT-DN}}";
$defhost= "{{SERVER-NAME}}";
$defport= "{{SERVER-PORT}}";

# User values
$rootdn= "{{ROOT-DN}}";
$rootpw= "";
$pwfile= "";
$host= "{{SERVER-NAME}}";
$port= "{{SERVER-PORT}}";
$entry= "";

$single=0;
$role=0;

# Process the command line arguments
while( $arg = shift)
{
    if($arg eq "-?")
    {
        usage_and_exit();
    }
    elsif($arg eq "-D")
    {
        $rootdn= shift @ARGV;
    }
    elsif($arg eq "-w")
    {
        $rootpw= shift @ARGV;
    }
    elsif($arg eq "-j")
    {
        $pwfile= shift @ARGV;
    }
    elsif($arg eq "-p")
    {
        $port= shift @ARGV;
    }
    elsif($arg eq "-h")
    {
        $host= shift @ARGV;
    }
    elsif($arg eq "-I")
    {
        $entry= shift @ARGV;
    }
	else
	{
		print "$arg: Unknown command line argument.\n";
		usage_and_exit();
	}
}

if ($pwfile ne ""){
# Open file and get the password
	unless (open (RPASS, $pwfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$rootpw = <RPASS>;
	chomp($rootpw);
	close(RPASS);
} elsif ($rootpw eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$rootpw = ReadLine(0); 
#	chomp($rootpw);
#	ReadMode('normal');
}

if( $rootpw eq "" )
{
	usage_and_exit();
}

if( $entry eq "" )
{
	usage_and_exit();
}

#
# Check the actual existence of the entry to inactivate/activate
# and at the same time, validate the various parm: port, host, rootdn, rootpw
#
@exist=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" dn`;
$retCode1=$?;
if ( $retCode1 != 0 )
{
	$retCode1=$?>>8;
	exit $retCode1;
}

@isRole=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(&(objectclass=LDAPsubentry)(objectclass=nsRoleDefinition))\" dn`;
$nbLineRole=@isRole;
$retCode2=$?;
if ( $retCode2 != 0 )
{
	$retCode2=$?>>8;
	exit $retCode2;
}

if ( $nbLineRole == 1 )
{
	debug("Groups of users\n");
	$role=1;
}
else
{
	debug("Single user\n");
	$single=1;
}

#
# First of all, check the existence of the nsaccountlock attribute in the entry
#
$isLocked=0;
if ( $single == 1 )
{
	$searchAccountLock="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" nsaccountlock";
	open (LDAP1, "$searchAccountLock |");
	while (<LDAP1>) {
		s/\n //g;
		if (/^nsaccountlock: (.*)\n/) {
			$L_currentvalue = $1;
			$L_currentvalue=~ tr/A-Z/a-z/;
			if ( $L_currentvalue eq "true")
			{
				$isLocked=1;
			}
			elsif ( $L_currentvalue eq "false" )
			{
				$isLocked=0;
			}
		}
	}
	close(LDAP1);
}
debug("Is the entry already locked? ==> $isLocked\n");

#
# Get the suffix name of that entry
#

# Remove the space at the beginning (just in case...)
#	-I "uid=jvedder , ou=People , o=sun.com"
@suffix=split /([,])/,$entry;
$result="";
foreach $part (@suffix)
{
	$part=~s/^ +//;
	$part=~ tr/A-Z/a-z/;
	$result="$result$part";
}
@suffixN=$result;

debug("Entry to $operation: #@suffix#\n");
debug("Entry to $operation: #@suffixN#\n");

# Get the suffix
$cont=0;
while ($cont == 0)
{
	# Look if suffix is the suffix of the entry
	#	ldapsearch -s one -b "cn=mapping tree,cn=config" "cn=\"uid=jvedder,ou=People,o=sun.com\""
	#
	debug("\tSuffix from the entry: #@suffixN#\n");
	@mapping=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s one -b \"cn=mapping tree, cn=config\" \"cn=\\"@suffixN\\"\" cn `;

	$retCode=$?;
	if ( $retCode != 0 )
	{
		$retCode=$?>>8;
		exit $retCode;
	}

	# If we get a result, remove the dn:
	#	dn: cn="o=sun.com",cn=mapping tree,cn=config
	#	cn: "o=sun.com"
	#
	shift @mapping;

	foreach $res (@mapping)
	{
		# Break the string cn: "o=sun.com" into pieces
		@cn= split(/ /,$res);

		# And remove the cn: part
		shift @cn;

		# Now compare the suffix we extract from the mapping tree 
		# with the suffix derived from the entry
		debug("\tSuffix from mapping tree: #@cn#\n");
		if ( @cn eq @suffixN ) {
			debug("Found matching suffix\n");
			$cont=1;
		}
	}

	if ( $cont == 0 )
	{
		# Remove the current rdn to try another suffix
		shift @suffix;

		$result="";
		foreach $part (@suffix)
		{
			$part=~ s/^ +//;
			$part=~ tr/A-Z/a-z/;
			$result="$result$part";
		}
		@suffixN=$result;

		debug("\t\tNothing found => go up one level in rdn #@suffix#\n");
		$len=@suffix;
		if ( $len == 0 )
		{
			debug("Can not find suffix. Problem\n");
			$cont=2;
		}
	}
}
if ( $cont == 2)
{
	out("Can not find suffix for entry $entry\n");
	exit 100;
}

if ( $operation eq "inactivate" )
{
	#
	# Now that we have the suffix and we know if we deal with a single entry or
	# a role, just try to create the COS and roles associated.
	#
	@base=(
		"cn=nsManagedDisabledRole, at suffixN",
		"cn=nsDisabledRole, at suffixN",
		"cn=nsAccountInactivationTmp, at suffixN",
		"\'cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\'",
		"cn=nsAccountInactivation_cos, at suffixN" );

	$addrolescos="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c -a >> {{DEV-NULL}} 2>&1 ";
	@role1=(
		"dn: cn=nsManagedDisabledRole, at suffixN\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsSimpleRoleDefinition\n",
		"objectclass: nsManagedRoleDefinition\n",
		"cn: nsManagedDisabledRole\n\n" );
	@role2=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsComplexRoleDefinition\n",
		"objectclass: nsNestedRoleDefinition\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n",
		"cn: nsDisabledRole\n\n" );
	@cos1=(
		"dn: cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: nsContainer\n\n" );
	@cos2=(
		"dn: cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: extensibleObject\n",
		"objectclass: costemplate\n",
		"objectclass: ldapsubentry\n",
		"cosPriority: 1\n",
		"nsAccountLock: true\n\n" );
	@cos3=(
		"dn: cn=nsAccountInactivation_cos, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: cosSuperDefinition\n",
		"objectclass: cosClassicDefinition\n",
		"cosTemplateDn: cn=nsAccountInactivationTmp, at suffixN\n",
		"cosSpecifier: nsRole\n",
		"cosAttribute: nsAccountLock operational\n\n" );

	@all=(\@role1, \@role2, \@cos1, \@cos2, \@cos3);

	$i=0;

	foreach $current (@base)
	{
		debug("Creating $current ??\n");
		open(FD,"| $addrolescos ");
		print FD @{$all[$i]};
		close(FD);
		if ( $? != 0 )
		{
			$retCode=$?>>8;
			if ( $retCode == 68 )
			{
				debug("Entry $current already exists, ignore error\n");
			}
			else
			{
				# Probably a more serious problem.
				# Exit with LDAP error
				exit $retCode;
			}
		}
		else
		{
			debug("Entry $current created\n");
		}
		$i=$i+1;
	}
}

$skipManaged=0;
$skipDisabled=0;
$directLocked=0;

$nsDisabledRole="cn=nsDisabledRole, at suffixN";
$nsDisabledRole=~ tr/A-Z/a-z/;

$nsManagedDisabledRole="cn=nsManagedDisabledRole, at suffixN";
$nsManagedDisabledRole=~ tr/A-Z/a-z/;

if ( $operation eq "inactivate" )
{
	# Go through all the roles part of nsdisabledrole to check if the entry
	# is a member of one of those roles
	$ret=indirectLock("LDAP00", $entry, $nsDisabledRole);
	if ( $ret == 0 )
	{
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			# indirect lock
			out("$entry already $state through $throughRole.\n");
		}
		else
		{
			# direct lock
			out("$entry already $state.\n");
		}
		exit 100;
	}
	elsif ( $isLocked == 1 )
	{
		# the entry is not locked through a role, may be nsaccountlock is "hardcoded" ?
		out("$entry already $state (probably directly).\n");
		exit 103;
	}
}
elsif ( $operation eq "activate" || $operation eq "get status of" )
{
	$skipManaged=$single;
	$skipDisabled=$role;

	$ret=indirectLock("LDAP00",$entry, $nsDisabledRole);

	if ( $ret == 0 )
	{
		# undirectly locked
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			if ( $operation eq "activate" )
			{
				out("$entry inactivated through $throughRole. Can not activate it individually.\n");
				exit 100;
			}
			else
			{
				out("$entry inactivated through $throughRole.\n");
				exit 104;
			}
		}
		debug("$entry locked individually\n");

		if ( $operation ne "activate" )
		{
			out("$entry inactivated.\n");
			exit 103;
		}
	}
	elsif ( $directLocked == 0 )
	{
		if ( $operation eq "activate" && $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 100;
		}
		elsif ( $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 102;
		}
		else
		{
			# not locked using our schema, but nsaccountlock is probably present
			out("$entry inactivated (probably directly).\n");
			exit 103;
		}
	}
	elsif ( $operation ne "activate" )
	{
		out("$entry inactivated.\n");
		exit 103;
	}
	# else Locked directly, juste unlock it!
	debug("$entry locked individually\n");
}

#
# Inactivate/activate the entry
#
$action="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c >> {{DEV-NULL}} 2>&1";
if ( $single == 1 )
{
	@record=(
		"dn: $entry\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n\n" );
}
else
{
	@record=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: $entry\n\n" );
}
open(FD,"| $action ");
print FD @record;
close(FD);
if ( $? != 0 )
{
debug("$modrole, $entry\n");
	$retCode=$?>>8;
	exit $retCode;
}

out("$entry $state.\n");
exit 0;


--- NEW FILE template-ns-inactivate.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

###############################
# SUB-ROUTINES
###############################

sub usage_and_exit
{
	print (STDERR "$cmd [-D rootdn] { -w password | -w - | -j filename } \n");
	print (STDERR "     [-p port] [-h host] -I DN-to-$operation\n\n");
	print (STDERR "May be used to $operation a user or a domain of users\n\n");
	print (STDERR "Arguments:\n");
	print (STDERR "          -?                   - help\n");
	print (STDERR "          -D rootdn            - Provide a Directory Manager DN. Default= '$defrootdn'\n");
	print (STDERR "          -w password          - Provide a password for the Directory Manager DN\n");
	print (STDERR "          -w -                 - Prompt for the Directory Manager's password\n");
	print (STDERR "          -j filename          - Read the Directory Manager's password from file\n");
	print (STDERR "          -p port              - Provide a port. Default= '$defport'\n");
	print (STDERR "          -h host              - Provide a host name. Default= '$defhost'\n");
	print (STDERR "          -I DN-to-$operation  - Single entry DN or role DN to $operation\n");
	exit 100;
}

sub debug
{
#	print " ==> @_";
}

sub out
{
	print "@_";
}

# --------------------------
# Check if the entry is part of a locked role:
# i.e.: for each role member (nsroledn) of nsdisabledrole, check if
# 	* it is the same as the entry
# 	* the entry is member of role (==has nsroledn attributes), compare each of
#		them with the nsroledn of nsdisabledrole
#	* if nsroledn of nsdisabledrole are complex, go through each of them
# argv[0] is the local file handler
# argv[1] is the entry (may be a single entry DN or a role DN)
# argv[2] is the base for the search
# --------------------------

$throughRole="";

sub indirectLock
{
	# For recursivity, file handler must be local
	my $L_filehandle=$_[0];
	$L_filehandle++;

	my $L_entry=$_[1];
	# Remove useless space
    my @L_intern=split /([,])/,$L_entry;
    my $L_result="";
    foreach $L_part (@L_intern)
    {
        $L_part=~s/^ +//;
        $L_part=~ tr/A-Z/a-z/;
        $L_result="$L_result$L_part";
    }
    $L_entry=$L_result;

	my $L_base=$_[2];
	
	my $L_search;
	my $L_currentrole;
	my $L_retCode;

	my $L_local;

`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn >> {{DEV-NULL}} 2>&1 `;
$retCode=$?;
if ( $retCode != 0 )
{
    $retCode=$?>>8;
    return 1;
}

	# Check if the role is a nested role
	@L_Nested="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=nsNestedRoleDefinition)(objectclass=ldapsubentry))\"  ";
	# L_isNested == 1 means that we are going through a nested role, so for each member of that
	# nested role, check that the member is below the scope of the nested
	$L_isNested=@L_Nested;

	# Not Direct Lock, Go through roles if any
	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_base\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsroledn ";

	debug("\t-->indirectLock: check if $L_entry is part of a locked role from base $L_base\n\n");

	unless (open ($L_filehandle, "$L_search |")) 
	{
		out("Can't open file $L_filehandle\n");
		exit;
	}
	while (<$L_filehandle>) {

		s/\n //g;
		if (/^nsroledn: (.*)\n/) {
			$L_currentrole = $1;

			# Remove useless space
			my @L_intern=split /([,])/,$L_currentrole;
			my $L_result="";
			foreach $L_part (@L_intern)
			{
				$L_part=~s/^ +//;
				$L_part=~ tr/A-Z/a-z/;
				$L_result="$L_result$L_part";
			}
			$L_currentrole=$L_result;

			debug("\t-- indirectLock loop: current nsroledn $L_currentrole of base $L_base\n");
			if ( $L_isNested == 1 )
			{
				if ( checkScope($L_currentrole, $L_base) == 0 )
				{
					# Scope problem probably a bad conf, skip the currentrole
					next;	
				}
			}

			if ( $L_currentrole eq $L_entry )
			{
				# the entry is a role that is directly locked
				# i.e, nsroledn of nsdisabledrole contains the entry
				$throughRole=$L_base;
				$throughRole=~ tr/A-Z/a-z/;

				# skipDisabled means that we've just found that the entry (which is a role)
				# is locked directly (==its DN is part of nsroledn attributes)
				# we just want to know now, if it is locked through another role
				# at least, one
				if ( $skipDisabled == 1 )
				{
					# direct inactivation
					$directLocked=1;
					# just go through that test once
					$skipDisabled=0;
					next;
				}
				debug("\t-- 1 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			$L_retCode=memberOf($L_currentrole, $L_entry);
			if ( $L_retCode == 0 && $single == 1 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				if ( $skipManaged == 1 )
				{
					if ( $L_currentrole eq $nsManagedDisabledRole)
					{
						# Try next nsroledn
						$directLocked=1;
						$skipManaged=0;
						next;
					}
				} 
				debug("\t-- 2 indirectLock: $L_currentrole locked throughRole == $throughRole\n");
				return 0;
			}

			# Only for the first iteration
			# the first iteration is with nsdisabledrole as base, other
			# loops are deeper
			$L_local=$skipDisabled;
			$skipDisabled=0;
	
			# the current nsroledn may be a complex role, just go through
			# its won nsroledn
			$L_retCode=indirectLock($L_filehandle,$L_entry, $L_currentrole);

			# Because of recursivity, to keep the initial value for the first level
			$skipDisabled=$L_local;

			if ( $L_retCode == 0 )
			{
				$throughRole=$L_currentrole;
				$throughRole=~ tr/A-Z/a-z/;
				debug("\t-- 3 indirectLock: $L_entry locked throughRole == $throughRole\n");
				return 0;
			}
		}
	}

	close($L_filehandle);

	debug("\t<--indirectLock: no more nsroledn to process\n");
	return 1;
}

# --------------------------
# Check if nsroledn is part of the entry attributes
# argv[0] is a role DN (nsroledn attribute)
# argv[1] is the entry
# --------------------------
sub memberOf
{
	my $L_nsroledn=$_[0];
	$L_nsroledn=~ tr/A-Z/a-z/;

	my $L_entry=$_[1];

	my $L_search;
	my $L_currentrole;

	$L_search="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$L_entry\" \"(|(objectclass=*)(objectclass=ldapsubentry))\" nsrole";

	debug("\t\t-->memberOf: $L_search: check if $L_entry has $L_nsroledn as nsroledn attribute\n");

	open (LDAP2, "$L_search |");
	while (<LDAP2>) {
		s/\n //g;
		if (/^nsrole: (.*)\n/) {
			$L_currentrole = $1;
			$L_currentrole=~ tr/A-Z/a-z/;
			if ( $L_currentrole eq $L_nsroledn )
			{
				# the parm is part of the $L_entry nsroledn
				debug("\t\t<--memberOf: $L_entry locked through $L_nsroledn\n");
				return 0;
			}
		}
	}
	close(LDAP2);

	# the parm is not part of the $L_entry nsroledn
	debug("\t\t<--memberOf: $L_entry not locked through $L_nsroledn\n");
	return 1;
}


# --------------------------
# Remove the rdn of a DN
# argv[0] is a DN
# --------------------------
sub removeRdn
{
    $L_entry=$_[0];

    @L_entryToTest=split /([,])/,$L_entry;
    debug("removeRdn: entry to split: $L_entry**@L_entryToTest\n");

    $newDN="";
    $removeRDN=1;
    foreach $part (@L_entryToTest)
    {
        $part=~ s/^ +//;
        $part=~ tr/A-Z/a-z/;
        if ( $removeRDN <= 2 )
        {
            $removeRDN=$removeRDN+1;
        }
        else
        {
            $newDN="$newDN$part";
        }
    }

    debug("removeRdn: new DN **$newDN**\n");
}

# --------------------------
# Check if L_current is below the scope of 
# L_nestedRole
# argv[0] is a role
# argv[1] is the nested role
# --------------------------
sub checkScope
{
    $L_current=$_[0];
    $L_nestedRole=$_[1];

    debug("checkScope: check if $L_current is below $L_nestedRole\n");

    removeRdn($L_nestedRole);
    $L_nestedRoleSuffix=$newDN;
    debug("checkScope: nested role based:  $L_nestedRoleSuffix\n");

    $cont=1;
    while ( ($cont == 1) && ($L_current ne "") )
    {
        removeRdn($L_current);
        $currentDn=$newDN;
        debug("checkScope: current DN to check: $currentDn\n");
 
        if ( $currentDn eq $L_nestedRoleSuffix )
        {
            debug("checkScope: DN match!!!\n");
            $cont = 0;
        }
        else
        {
            $L_current=$currentDn;
        }
    }
 
    if ( $cont == 1 )
    {
        debug("checkScope: $_[0] and $_[1] are not compatible\n");
        return 0;
    }
    else
    {
        debug("checkScope: $_[0] and $_[1] are compatible\n");
        return 1;
    }
}


###############################
# MAIN ROUTINE
###############################

# Generated variable
$prefix="{{DS-ROOT}}";

# Determine which command we are running
if ( $0 =~ /ns-inactivate(.pl)?$/ )
{
	$cmd="ns-inactivate.pl";
	$operation="inactivate";
	$state="inactivated";
	$modrole="add";
	$already="already";
}
elsif ( $0 =~ /ns-activate(.pl)?$/ )
{
	$cmd="ns-activate.pl";
	$operation="activate";
	$state="activated";
	$modrole="delete";
	$already="already";
}
elsif ( $0 =~ /ns-accountstatus(.pl)?$/ )
{
	$cmd="ns-accountstatus.pl";
	$operation="get status of";
	$state="activated";
	# no need for $modrole as no operation is performed
	$already="";

}
else
{
	out("$0: unknown command\n");
	exit 100;
}

debug("Running ** $cmd ** $operation\n");

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

$ldapsearch="ldapsearch -1";
$ldapmodify="ldapmodify";
 
# Default values
$defrootdn= "{{ROOT-DN}}";
$defhost= "{{SERVER-NAME}}";
$defport= "{{SERVER-PORT}}";

# User values
$rootdn= "{{ROOT-DN}}";
$rootpw= "";
$pwfile= "";
$host= "{{SERVER-NAME}}";
$port= "{{SERVER-PORT}}";
$entry= "";

$single=0;
$role=0;

# Process the command line arguments
while( $arg = shift)
{
    if($arg eq "-?")
    {
        usage_and_exit();
    }
    elsif($arg eq "-D")
    {
        $rootdn= shift @ARGV;
    }
    elsif($arg eq "-w")
    {
        $rootpw= shift @ARGV;
    }
    elsif($arg eq "-j")
    {
        $pwfile= shift @ARGV;
    }
    elsif($arg eq "-p")
    {
        $port= shift @ARGV;
    }
    elsif($arg eq "-h")
    {
        $host= shift @ARGV;
    }
    elsif($arg eq "-I")
    {
        $entry= shift @ARGV;
    }
	else
	{
		print "$arg: Unknown command line argument.\n";
		usage_and_exit();
	}
}

if ($pwfile ne ""){
# Open file and get the password
	unless (open (RPASS, $pwfile)) {
		die "Error, cannot open password file $passwdfile\n";
	}
	$rootpw = <RPASS>;
	chomp($rootpw);
	close(RPASS);
} elsif ($rootpw eq "-"){
# Read the password from terminal
	die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n",
	    "part of the standard perl distribution. If you want to use it, you must\n",
	    "download and install the module. You can find it at\n",
	    "http://www.perl.com/CPAN/CPAN.html\n";
# Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module.
# use Term::ReadKey; 
#	print "Bind Password: ";
#	ReadMode('noecho'); 
#	$rootpw = ReadLine(0); 
#	chomp($rootpw);
#	ReadMode('normal');
}

if( $rootpw eq "" )
{
	usage_and_exit();
}

if( $entry eq "" )
{
	usage_and_exit();
}

#
# Check the actual existence of the entry to inactivate/activate
# and at the same time, validate the various parm: port, host, rootdn, rootpw
#
@exist=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" dn`;
$retCode1=$?;
if ( $retCode1 != 0 )
{
	$retCode1=$?>>8;
	exit $retCode1;
}

@isRole=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(&(objectclass=LDAPsubentry)(objectclass=nsRoleDefinition))\" dn`;
$nbLineRole=@isRole;
$retCode2=$?;
if ( $retCode2 != 0 )
{
	$retCode2=$?>>8;
	exit $retCode2;
}

if ( $nbLineRole == 1 )
{
	debug("Groups of users\n");
	$role=1;
}
else
{
	debug("Single user\n");
	$single=1;
}

#
# First of all, check the existence of the nsaccountlock attribute in the entry
#
$isLocked=0;
if ( $single == 1 )
{
	$searchAccountLock="$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s base -b \"$entry\" \"(objectclass=*)\" nsaccountlock";
	open (LDAP1, "$searchAccountLock |");
	while (<LDAP1>) {
		s/\n //g;
		if (/^nsaccountlock: (.*)\n/) {
			$L_currentvalue = $1;
			$L_currentvalue=~ tr/A-Z/a-z/;
			if ( $L_currentvalue eq "true")
			{
				$isLocked=1;
			}
			elsif ( $L_currentvalue eq "false" )
			{
				$isLocked=0;
			}
		}
	}
	close(LDAP1);
}
debug("Is the entry already locked? ==> $isLocked\n");

#
# Get the suffix name of that entry
#

# Remove the space at the beginning (just in case...)
#	-I "uid=jvedder , ou=People , o=sun.com"
@suffix=split /([,])/,$entry;
$result="";
foreach $part (@suffix)
{
	$part=~s/^ +//;
	$part=~ tr/A-Z/a-z/;
	$result="$result$part";
}
@suffixN=$result;

debug("Entry to $operation: #@suffix#\n");
debug("Entry to $operation: #@suffixN#\n");

# Get the suffix
$cont=0;
while ($cont == 0)
{
	# Look if suffix is the suffix of the entry
	#	ldapsearch -s one -b "cn=mapping tree,cn=config" "cn=\"uid=jvedder,ou=People,o=sun.com\""
	#
	debug("\tSuffix from the entry: #@suffixN#\n");
	@mapping=`$ldapsearch -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -s one -b \"cn=mapping tree, cn=config\" \"cn=\\"@suffixN\\"\" cn `;

	$retCode=$?;
	if ( $retCode != 0 )
	{
		$retCode=$?>>8;
		exit $retCode;
	}

	# If we get a result, remove the dn:
	#	dn: cn="o=sun.com",cn=mapping tree,cn=config
	#	cn: "o=sun.com"
	#
	shift @mapping;

	foreach $res (@mapping)
	{
		# Break the string cn: "o=sun.com" into pieces
		@cn= split(/ /,$res);

		# And remove the cn: part
		shift @cn;

		# Now compare the suffix we extract from the mapping tree 
		# with the suffix derived from the entry
		debug("\tSuffix from mapping tree: #@cn#\n");
		if ( @cn eq @suffixN ) {
			debug("Found matching suffix\n");
			$cont=1;
		}
	}

	if ( $cont == 0 )
	{
		# Remove the current rdn to try another suffix
		shift @suffix;

		$result="";
		foreach $part (@suffix)
		{
			$part=~ s/^ +//;
			$part=~ tr/A-Z/a-z/;
			$result="$result$part";
		}
		@suffixN=$result;

		debug("\t\tNothing found => go up one level in rdn #@suffix#\n");
		$len=@suffix;
		if ( $len == 0 )
		{
			debug("Can not find suffix. Problem\n");
			$cont=2;
		}
	}
}
if ( $cont == 2)
{
	out("Can not find suffix for entry $entry\n");
	exit 100;
}

if ( $operation eq "inactivate" )
{
	#
	# Now that we have the suffix and we know if we deal with a single entry or
	# a role, just try to create the COS and roles associated.
	#
	@base=(
		"cn=nsManagedDisabledRole, at suffixN",
		"cn=nsDisabledRole, at suffixN",
		"cn=nsAccountInactivationTmp, at suffixN",
		"\'cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\'",
		"cn=nsAccountInactivation_cos, at suffixN" );

	$addrolescos="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c -a >> {{DEV-NULL}} 2>&1 ";
	@role1=(
		"dn: cn=nsManagedDisabledRole, at suffixN\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsSimpleRoleDefinition\n",
		"objectclass: nsManagedRoleDefinition\n",
		"cn: nsManagedDisabledRole\n\n" );
	@role2=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: nsRoleDefinition\n",
		"objectclass: nsComplexRoleDefinition\n",
		"objectclass: nsNestedRoleDefinition\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n",
		"cn: nsDisabledRole\n\n" );
	@cos1=(
		"dn: cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: nsContainer\n\n" );
	@cos2=(
		"dn: cn=\"cn=nsDisabledRole, at suffixN\",cn=nsAccountInactivationTmp, at suffixN\n",
		"objectclass: top\n",
		"objectclass: extensibleObject\n",
		"objectclass: costemplate\n",
		"objectclass: ldapsubentry\n",
		"cosPriority: 1\n",
		"nsAccountLock: true\n\n" );
	@cos3=(
		"dn: cn=nsAccountInactivation_cos, at suffixN\n",
		"objectclass: top\n",
		"objectclass: LDAPsubentry\n",
		"objectclass: cosSuperDefinition\n",
		"objectclass: cosClassicDefinition\n",
		"cosTemplateDn: cn=nsAccountInactivationTmp, at suffixN\n",
		"cosSpecifier: nsRole\n",
		"cosAttribute: nsAccountLock operational\n\n" );

	@all=(\@role1, \@role2, \@cos1, \@cos2, \@cos3);

	$i=0;

	foreach $current (@base)
	{
		debug("Creating $current ??\n");
		open(FD,"| $addrolescos ");
		print FD @{$all[$i]};
		close(FD);
		if ( $? != 0 )
		{
			$retCode=$?>>8;
			if ( $retCode == 68 )
			{
				debug("Entry $current already exists, ignore error\n");
			}
			else
			{
				# Probably a more serious problem.
				# Exit with LDAP error
				exit $retCode;
			}
		}
		else
		{
			debug("Entry $current created\n");
		}
		$i=$i+1;
	}
}

$skipManaged=0;
$skipDisabled=0;
$directLocked=0;

$nsDisabledRole="cn=nsDisabledRole, at suffixN";
$nsDisabledRole=~ tr/A-Z/a-z/;

$nsManagedDisabledRole="cn=nsManagedDisabledRole, at suffixN";
$nsManagedDisabledRole=~ tr/A-Z/a-z/;

if ( $operation eq "inactivate" )
{
	# Go through all the roles part of nsdisabledrole to check if the entry
	# is a member of one of those roles
	$ret=indirectLock("LDAP00", $entry, $nsDisabledRole);
	if ( $ret == 0 )
	{
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			# indirect lock
			out("$entry already $state through $throughRole.\n");
		}
		else
		{
			# direct lock
			out("$entry already $state.\n");
		}
		exit 100;
	}
	elsif ( $isLocked == 1 )
	{
		# the entry is not locked through a role, may be nsaccountlock is "hardcoded" ?
		out("$entry already $state (probably directly).\n");
		exit 103;
	}
}
elsif ( $operation eq "activate" || $operation eq "get status of" )
{
	$skipManaged=$single;
	$skipDisabled=$role;

	$ret=indirectLock("LDAP00",$entry, $nsDisabledRole);

	if ( $ret == 0 )
	{
		# undirectly locked
		if ( $throughRole ne $nsDisabledRole && $throughRole ne $nsManagedDisabledRole )
		{
			if ( $operation eq "activate" )
			{
				out("$entry inactivated through $throughRole. Can not activate it individually.\n");
				exit 100;
			}
			else
			{
				out("$entry inactivated through $throughRole.\n");
				exit 104;
			}
		}
		debug("$entry locked individually\n");

		if ( $operation ne "activate" )
		{
			out("$entry inactivated.\n");
			exit 103;
		}
	}
	elsif ( $directLocked == 0 )
	{
		if ( $operation eq "activate" && $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 100;
		}
		elsif ( $isLocked != 1 )
		{
			out("$entry $already $state.\n");
			exit 102;
		}
		else
		{
			# not locked using our schema, but nsaccountlock is probably present
			out("$entry inactivated (probably directly).\n");
			exit 103;
		}
	}
	elsif ( $operation ne "activate" )
	{
		out("$entry inactivated.\n");
		exit 103;
	}
	# else Locked directly, juste unlock it!
	debug("$entry locked individually\n");
}

#
# Inactivate/activate the entry
#
$action="$ldapmodify -p $port -h $host -D \"$rootdn\" -w \"$rootpw\" -c >> {{DEV-NULL}} 2>&1";
if ( $single == 1 )
{
	@record=(
		"dn: $entry\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: cn=nsManagedDisabledRole, at suffixN\n\n" );
}
else
{
	@record=(
		"dn: cn=nsDisabledRole, at suffixN\n",
		"changetype: modify\n",
		"$modrole: nsRoleDN\n",
		"nsRoleDN: $entry\n\n" );
}
open(FD,"| $action ");
print FD @record;
close(FD);
if ( $? != 0 )
{
debug("$modrole, $entry\n");
	$retCode=$?>>8;
	exit $retCode;
}

out("$entry $state.\n");
exit 0;


--- NEW FILE template-ns-newpwpolicy.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

# enable the use of our bundled perldap with our bundled ldapsdk libraries
# all of this nonsense can be omitted if the mozldapsdk and perldap are
# installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5)
$prefix = "{{DS-ROOT}}";

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
# Add new password policy specific entries

#############################################################################
# enable the use of Perldap functions
require DynaLoader;

use Getopt::Std;
use Mozilla::LDAP::Conn;
use Mozilla::LDAP::Utils qw(:all);
use Mozilla::LDAP::API qw(:api :ssl :apiv3 :constant); # Direct access to C API

#############################################################################
# Default values of the variables

$opt_D = "{{ROOT-DN}}";
$opt_p = "{{SERVER-PORT}}";
$opt_h = "{{SERVER-NAME}}";
$opt_v = 0;

# Variables
$ldapsearch="ldapsearch -1";
$ldapmodify="ldapmodify";

#############################################################################

sub usage {
	print (STDERR "ns-newpwpolicy.pl [-v] [-D rootdn] { -w password | -j filename } \n");
	print (STDERR "                  [-p port] [-h host] -U UserDN -S SuffixDN\n\n");

	print (STDERR "Arguments:\n");
	print (STDERR "	-?		- help\n");
	print (STDERR "	-v		- verbose output\n");
	print (STDERR "	-D rootdn	- Directory Manager DN. Default= '$opt_D'\n");
	print (STDERR "	-w rootpw	- password for the Directory Manager DN\n");
	print (STDERR "	-j filename	- Read the Directory Manager's password from file\n");
	print (STDERR "	-p port		- port. Default= $opt_p\n");
	print (STDERR "	-h host		- host name. Default= '$opt_h'\n");
	print (STDERR "	-U userDN	- User entry DN\n");
	print (STDERR "	-S suffixDN	- Suffix entry DN\n");
	exit 100;
}

# Process the command line arguments
{
	usage() if (!getopts('vD:w:j:p:h:U:S:'));

	if ($opt_j ne ""){
		die "Error, cannot open password file $opt_j\n" unless (open (RPASS, $opt_j));
		$opt_w = <RPASS>;
		chomp($opt_w);
		close(RPASS);
	} 

	usage() if( $opt_w eq "" );
	if ($opt_U eq "" && $opt_S eq "") {
		print (STDERR "Please provide at least -S or -U option.\n\n");
	}

	# Now, check if the user/group exists

	if ($opt_S) {
		print (STDERR "host = $opt_h, port = $opt_p, suffixDN = \"$opt_S\"\n\n") if $opt_v;
		@base=(
			"cn=nsPwPolicyContainer,$opt_S",
			"cn=\"cn=nsPwPolicyEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S",
			"cn=\"cn=nsPwTemplateEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S",
			"cn=nsPwPolicy_cos,$opt_S"
		);

		$ldapadd="$ldapmodify -p $opt_p -h $opt_h -D \"$opt_D\" -w \"$opt_w\" -c -a 2>&1";
		$modifyCfg="$ldapmodify -p $opt_p -h $opt_h -D \"$opt_D\" -w \"$opt_w\" -c 2>&1";

		@container=(
			"dn: cn=nsPwPolicyContainer,$opt_S\n",
			"objectclass: top\n",
			"objectclass: nsContainer\n\n" );
		@pwpolicy=(
			"dn: cn=\"cn=nsPwPolicyEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S\n",
			"objectclass: top\n",
			"objectclass: ldapsubentry\n",
			"objectclass: passwordpolicy\n\n" );
		@template=(
			"dn: cn=\"cn=nsPwTemplateEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S\n",
			"objectclass: top\n",
			"objectclass: extensibleObject\n",
			"objectclass: costemplate\n",
			"objectclass: ldapsubentry\n",
			"cosPriority: 1\n",
			"pwdpolicysubentry: cn=\"cn=nsPwPolicyEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S\n\n" );
		@cos=(
			"dn: cn=nsPwPolicy_cos,$opt_S\n",
			"objectclass: top\n",
			"objectclass: LDAPsubentry\n",
			"objectclass: cosSuperDefinition\n",
			"objectclass: cosPointerDefinition\n",
			"cosTemplateDn: cn=\"cn=nsPwTemplateEntry,$opt_S\",cn=nsPwPolicyContainer,$opt_S\n",
			"cosAttribute: pwdpolicysubentry default operational-default\n\n" );

		@all=(\@container, \@pwpolicy, \@template, \@cos);

        $i=0;

        foreach $current (@base)
        {
			open(FD,"| $ldapadd");
			print FD @{$all[$i]};
			close(FD);
			if ( $? != 0 ) {
				$retCode=$?>>8;
				if ( $retCode == 68 ) {
					print( STDERR "Entry \"$current\" already exists. Please ignore the error\n\n");
				}
				else {
					# Probably a more serious problem.
					# Exit with LDAP error
					print(STDERR "Error $retcode while adding \"$current\". Exiting.\n");
					exit $retCode;
				}
			}
			else {
				print( STDERR "Entry \"$current\" created\n\n") if $opt_v;
			}
			$i=$i+1;
		}

		$modConfig = "dn:cn=config\nchangetype: modify\nreplace:nsslapd-pwpolicy-local\nnsslapd-pwpolicy-local: on\n\n";
		open(FD,"| $modifyCfg ");
		print(FD $modConfig);
		close(FD);
		$retcode = $?;
		if ( $retcode != 0 ) {
			print( STDERR "Error $retcode while modifing \"cn=config\". Exiting.\n" );
			exit ($retcode);
		}
		else {
			print( STDERR "Entry \"cn=config\" modified\n\n") if $opt_v;
		}
	} # end of $opt_S

	if ($opt_U) {
		my $norm_opt_U = normalizeDN($opt_U);
		print (STDERR "host = $opt_h, port = $opt_p, userDN = \"$norm_opt_U\"\n\n") if $opt_v;
		$retcode = `$ldapsearch -h $opt_h -p $opt_p -b \"$norm_opt_U\" -s base \"\"`;
		if ($retcode != 0 ) {
			print( STDERR "the user entry $norm_opt_U does not exist. Exiting.\n");
			exit ($retcode);
		}
		
		print( STDERR "the user entry $norm_opt_U found..\n\n") if $opt_v;
		
		# Now, get the parentDN 
		@rdns = ldap_explode_dn($norm_opt_U, 0);
		shift @rdns;
		$parentDN = join(',', @rdns);

		print (STDERR "parentDN is $parentDN\n\n") if $opt_v;

		@base=(
			"cn=nsPwPolicyContainer,$parentDN",
			"cn=\"cn=nsPwPolicyEntry,$norm_opt_U\",cn=nsPwPolicyContainer,$parentDN"
		);

		$ldapadd="$ldapmodify -p $opt_p -h $opt_h -D \"$opt_D\" -w \"$opt_w\" -c -a 2>&1";
		$modifyCfg="$ldapmodify -p $opt_p -h $opt_h -D \"$opt_D\" -w \"$opt_w\" -c 2>&1";

		@container=(
			"dn: cn=nsPwPolicyContainer,$parentDN\n",
			"objectclass: top\n",
			"objectclass: nsContainer\n\n" );
		@pwpolicy=(
			"dn: cn=\"cn=nsPwPolicyEntry,$norm_opt_U\",cn=nsPwPolicyContainer,$parentDN\n",
			"objectclass: top\n",
			"objectclass: ldapsubentry\n",
			"objectclass: passwordpolicy\n\n" );

		@all=(\@container, \@pwpolicy);

        $i=0;

        foreach $current (@base)
        {
			open(FD,"| $ldapadd ");
			print FD @{$all[$i]};
			close(FD);
			if ( $? != 0 ) {
				$retCode=$?>>8;
				if ( $retCode == 68 ) {
					print( STDERR "Entry $current already exists. Please ignore the error\n\n");
				}
				else {
					# Probably a more serious problem.
					# Exit with LDAP error
					print(STDERR "Error $retcode while adding \"$current\". Exiting.\n");
					exit $retCode;
				}
			}
			else {
				print( STDERR "Entry $current created\n\n") if $opt_v;
			}
			$i=$i+1;
		}

		$target = "cn=\"cn=nsPwPolicyEntry,$norm_opt_U\",cn=nsPwPolicyContainer,$parentDN";
		$modConfig = "dn: $norm_opt_U\nchangetype: modify\nreplace:pwdpolicysubentry\npwdpolicysubentry: $target\n\n";
		open(FD,"| $modifyCfg ");
		print(FD $modConfig);
		close(FD);
		$retcode = $?;
		if ( $retcode != 0 ) {
			print( STDERR "Error $retcode while modifing $norm_opt_U. Exiting.\n" );
			exit ($retcode);
		}
		else {
			print( STDERR "Entry \"$norm_opt_U\" modified\n\n") if $opt_v;
		}

		$modConfig = "dn:cn=config\nchangetype: modify\nreplace:nsslapd-pwpolicy-local\nnsslapd-pwpolicy-local: on\n\n";
		open(FD,"| $modifyCfg ");
		print(FD $modConfig);
		close(FD);
		$retcode = $?;
		if ( $retcode != 0 ) {
			print( STDERR "Error $retcode while modifing \"cn=config\". Exiting.\n" );
			exit ($retcode);
		}
		else {
			print( STDERR "Entry \"cn=config\" modified\n\n") if $opt_v;
		}
	} # end of $opt_U
}


--- NEW FILE template-repl-monitor-cgi.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

use Cgi;

$params = "";
$params .= " -h $cgiVars{'servhost'}" if $cgiVars{'servhost'};
$params .= " -p $cgiVars{'servport'}" if $cgiVars{'servport'};
$params .= " -f $cgiVars{'configfile'}" if $cgiVars{'configfile'};
$params .= " -t $cgiVars{'refreshinterval'}" if $cgiVars{'refreshinterval'};
if ($cgiVars{'admurl'}) {
	$admurl = "$cgiVars{'admurl'}";
	if ( $ENV{'QUERY_STRING'} ) {
		$admurl .= "?$ENV{'QUERY_STRING'}";
	}
	elsif ( $ENV{'CONTENT_LENGTH'} ) {
		$admurl .= "?$Cgi::CONTENT";
	}
	$params .= " -u \"$admurl\"";
}
$siteroot = $cgiVars{'siteroot'};
$prefix = "{{DS-ROOT}}";

$ENV{'PATH'} = '$prefix at ldapsdk_bindir@:$prefix/usr/lib:@ldapsdk_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '$prefix at nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib';

# Save user-specified parameters as cookies in monreplication.properties.
# Sync up with the property file so that monreplication2 is interval, and
# monreplication3 the config file pathname.
$propertyfile = "$siteroot/bin/admin/admin/bin/property/monreplication.properties";
$edit1 = "s#monreplication2=.*#monreplication2=$cgiVars{'refreshinterval'}#;";
$edit2 = "s#^monreplication3=.*#monreplication3=$cgiVars{'configfile'}#;";
system("perl -p -i.bak -e \"$edit1\" -e \"$edit2\" $propertyfile");

# Now the real work
$replmon = "$siteroot/bin/slapd/admin/scripts/template-repl-monitor.pl";
system("perl -I$siteroot/lib/perl/arch -I$siteroot/lib/perl $replmon $params");


--- NEW FILE template-repl-monitor.pl.in ---
#{{PERL-EXEC}}
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
##############################################################################
#
# FILE: repl-monitor.pl
#
# SYNOPSIS:
#    repl-monitor.pl -f configuration-file [-h host] [-p port] [-r] \
#                    [-u refresh-url] [-t refresh-interval]
#
#    repl-monitor.pl -v
#
# DESCRIPTION:
#    Given an LDAP replication "supplier" server, crawl over all the ldap
#    servers via direct or indirect replication agreements.
#    For each master replica discovered, display the maxcsn of the master
#    and the replication status of all its lower level replicas.
#    All output is in HTML.
#
# OPTIONS:
#
#    -f configuration-file
#	The configuration file contains the sections for the connection
#	parameters, the server alias, and the thresholds for different colors
#	when display the time lags between consumers and master.
#	If the Admin Server is running on Windows, the configuration-file
#	name may have format "D:/opt/replmon.conf".
#
#	The connection parameter section consists of the section name
#	followed by one of more connection parameter entries:
#
#		[connection]
#		host:port:binddn:bindpwd:bindcert
#		host:port=shadowport:binddn:bindpwd:bindcert
#		...
#
#   where host:port default (*:*) to that in a replication agreement,
#   binddn default (*) to "cn=Directory Manager", and bindcert is the
#	pathname of cert db if you want the script to connect to the server
#	via SSL.  If bindcert is omitted, the connection will be simple
#	bind.
#   "port=shadowport" means to use shadowport instead of port if port
#	is specified in the replication agreement. This is useful when
#	for example, ssl port is specified in a replication agreement,
#	but you can't access the cert db from the machine where this
#	script is running. So you could let the script to map the ssl
#	port to a non-ssl port and use the simple bind.
#
#	A server may have a dedicated or a share entry in the connection
#	section. The script will find out the most matched entry for a given
#	server. For example, if all the ldap servers except host1 share the
#	same binddn and bindpassword, the connection section then just need
#	two entries:
#
#		[connection]
# 		*:*:binddn:bindpassword:
# 		host1:*:binddn:bindpassword:
#
#	If a host:port is assigned an alias, then the alias instead of
#	host:port will be displayed in The output file. Each host:port
#	can have only one alias. But each alias may be used by more than
#	one host:port.
#
#		[alias]
#		alias = host:port
#		...
#
#	CSN time lags between masters and consumers might be displayed in
#	different colors based on their range. The thresholds for different
#	colors may be specified in color section:
#
#		[color]
#		lowmark (in minutes) = color
#		...
#	If the color section or color entry is missing, the default color
#	set is: green for [0-5) minutes lag, yellow [5-60), and red 60 and more.
#
#    -h host
#	Initial replication supplier's host. Default to the current host.
#
#    -p port
#	Initial replication supplier's port. Default to 389.
#
#    -r If specified, -r causes the routine to be entered without printing
#	HTML header information.  This is suitable when making multiple calls
#	to this routine (e.g. when specifying multiple, different, "unrelated"
#	supplier servers) and expecting a single HTML output. 
#
#    -t refresh-interval
#	Specify the refresh interval in seconds. This option has to be
#	jointly used with option -u.
#
#    -u refresh-url
#	The output HTML file may invoke a CGI program periodically. If
#	this CGI program in turn calls this script, the effect is that
#	the output HTML file would automatically refresh itself. This
#	is useful for continuing monitoring. See also option -t.
#
#    -v Print out the version of this script
# 
# DIAGNOSTICS:
#    There are several ways to invoke this script if you got error
#    "Can't locate Mozilla/LDAP/Conn.pm in @INC", or
#    "usage: Undefined variable":
#
#    1. Set the first line of the script to #!<DSHOME>/bin/slapd/admin/bin/perl
#	and run this script directly.
#
#    2. Run
#	<DSHOME>/bin/slapd/admin/bin/perl repl-monitor.pl
#
#    3. Set environment variable PERL5LIB to your Perl lib dirs where
#	Mozilla::LDAP module can be located.  This should be under serverroot/lib/perl
#   e.g. PERL5LIB="serverroot/lib/perl/arch:serverroot/lib/perl"
#
#    4. Set LD_LIBRARY_PATH (or SHLIB_PATH) to point to the location of our
#   bundled shared libraries e.g. LD_LIBRARY_PATH="serverroot/lib"
#
#    5. Invoke the script as follows if <MYPERLDIR> (serverroot/lib/perl) contains
#	Mozilla/LDAP:
#	<MYPERLDIR>/bin/perl -I <MYPERLDIR>/arch -I <MYPERLDIR> repl-monitor.pl
#
#############################################################################
# enable the use of our bundled perldap with our bundled ldapsdk libraries
# all of this nonsense can be omitted if the mozldapsdk and perldap are
# installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5)
# this script is always invoked by repl-monitor-cgi.pl, which sets all of these
# If using this script standalone, be sure to set the shared lib path and
# the path to the perldap modules.
$usage = "\nusage: $0 -f configuration-file [-h host] [-p port] [-r] [-u refresh-url] [-t refresh-interval]\n\nor   : $0 -v\n"; 

use Getopt::Std;		# parse command line arguments
use Mozilla::LDAP::Conn;	# LDAP module for Perl
use Mozilla::LDAP::Utils qw(normalizeDN);	# LULU, utilities.
use Mozilla::LDAP::API qw(:api :ssl :apiv3 :constant); # Direct access to C API
use Time::Local; # to convert GMT Z strings to localtime

#
# Global variables
#
$product = "Directory Server Replication Monitor";
$version = "Version 1.0";
#
# ldap servers given or discovered from the replication agreements:
# @servers		= (host:port=shadowport:binddn:password:cert_db)
#
# entries read from the connection section of the configuration file:
# @allconnections	= (host:port=shadowport:binddn:password:cert_db)
#
# aliases of ldap servers read from the configuration file:
# %allaliases{$host:$port}= (alias)
#
# replicas discovered on all ldap servers
# @allreplicas		= (server#:replicaroot:replicatype:serverid:replicadn)
#
# ruvs retrieved from all replicas
# @allruvs{replica#:masterid} = (rawcsn:decimalcsn;mon/day/year hh:mi:ss)
#
# agreements discovered on all ldap supplier servers:
# @allagreements	= (supplier_replica#:consumer#:conntype:schedule:status)
# the array may take another format after the consumer replicas are located:
# @allagreements	= (supplier_replica#:consumer_replica#:conntype:schedule:status)
#

#main
{
	# turn off buffered I/O
	$| = 1;

	# Check for legal options
	if (!getopts('h:p:f:ru:t:v')) {
		print $usage;
		exit -1;
  	}

	if ($opt_v) {
		print "$product - $version\n";
		exit;
	}

	$interval = $opt_t;
	$interval = 300 if ( !$interval || $interval <= 0 );

	# Get current date/time
	$nowraw = localtime();
	($wday, $mm, $dd, $tt, $yy) = split(/ /, $nowraw);
	$now = "$wday $mm $dd $yy $tt";

	# if no -r (Reenter and skip html header), print html header
	if (!$opt_r) {
		# print the HTML header
		&print_html_header;
	} else {
		# print separator for new replication set
		print "<hr width=90% size=3><br>\n";
	}

	exit -1 if &validateArgs < 0;
	exit if &read_cfg_file ($opt_f) < 0;

	# Start with the given host and port
	# The index names in %ld are defined in Mozilla::LDAP::Utils::ldapArgs()
	&add_server ("$ld{host}:$ld{port}:$ld{bind}:$ld{pswd}:$ld{cert}");

	$serveridx = 0;
	while ($serveridx <= $#servers) {
		if (&get_replicas ($serveridx) != 0 && $serveridx == 0) {
			my ($host, $port, $binddn) = split (/:/, $servers[0]);
			print("Login to $host:$port as \"$binddn\" failed\n");
			exit;
		}
		$serveridx++;
	} 

	&find_consumer_replicas;
	&process_suppliers;

	# All done! - well, for the current invokation only
	# print "</body></html>\n";
	exit;  
} 

sub validateArgs
{
	my ($rc) = 0;

	%ld = Mozilla::LDAP::Utils::ldapArgs();

	if (!$opt_v && !$opt_f) {
		print "<p>Error: Missing configuration file.\n";
		print "<p>If you need help on the configuration file, Please go back and click the Help button.\n";
		#print $usage;	# Don't show usage in CGI
		$rc = -1;
	}
	elsif (!$opt_h) {
		chop ($ld{"host"} = `hostname`);
	}

	return $rc;
}

sub read_cfg_file
{
	my ($fn) = @_;
	unless (open(CFGFILEHANDLE, $fn)) {
		print "<p>Error: Can't open \"$fn\": $!.\n";
		print "<p>If you need help on the configuration file, Please go back and click the Help button.\n";
		return -1;
	}
	$section = 0;
	while (<CFGFILEHANDLE>) {
		next if (/^\s*\#/ || /^\s*$/);
		chop ($_);
		if (m/^\[(.*)\]/) {
			$section = $1;
		}
		else {
			if ( $section =~ /conn/i ) {
				push (@allconnections, $_);
			}
			elsif ( $section =~ /alias/i ) {
				m/^\s*(\S.*)\s*=\s*(\S+)/;
				$allaliases {$2} = $1;
			}
			elsif ( $section =~ /color/i ) {
				m/^\s*(-?\d+)\s*=\s*(\S+)/;
				$allcolors {$1} = $2;
			}
		}
	}
	if ( ! keys (%allcolors) ) {
		$allcolors {0} = "#ccffcc";	#apple green
		$allcolors {5} = "#ffffcc";	#cream yellow
		$allcolors {60} = "#ffcccc";	#pale pink
	}
	@colorkeys = sort (keys (%allcolors));
	close (CFGFILEHANDLE);
	return 0;
}

sub get_replicas
{
	my ($serveridx) = @_;
	my ($conn, $host, $port, $shadowport, $binddn, $bindpwd, $bindcert);
	my ($others);
	my ($replica, $replicadn);
	my ($ruv, $replicaroot, $replicatype, $serverid, $masterid, $maxcsn);
	my ($type, $flag, $i);
	my ($myridx, $ridx, $cidx);

	#
	# Bind to the server
	#
	($host, $port, $binddn, $bindpwd, $bindcert) = split (/:/, "$servers[$serveridx]", 5);

	($port, $shadowport) = split (/=/, $port);
	$shadowport = $port if !$shadowport;

	$conn = new Mozilla::LDAP::Conn ($host, $shadowport, "$binddn", $bindpwd, $bindcert);

	return -1 if (!$conn);

	#
	# Get all the replica on the server
	#
	$myridx = $#allreplicas + 1;
	$replica = $conn->search ("cn=mapping tree,cn=config",
				"sub",
				"(objectClass=nsDS5Replica)", 0,
				qw(nsDS5ReplicaRoot nsDS5ReplicaType nsDS5Flags nsDS5ReplicaId));
	while ($replica) {
		$replicadn = $replica->getDN;
		$replicaroot = normalizeDN ($replica->{nsDS5ReplicaRoot}[0]);
		$type      = $replica->{nsDS5ReplicaType}[0];
		$flag      = $replica->{nsDS5Flags}[0];
		$serverid  = $replica->{nsDS5ReplicaId}[0];

		# flag = 0: change log is not created
		# type = 2: read only replica
		# type = 3: updatable replica
		$replicatype = $flag == 0 ? "consumer" : ($type == 2 ? "hub" : "master");

		push (@allreplicas, "$serveridx:$replicaroot:$replicatype:$serverid:$replicadn");

		$replica = $conn->nextEntry ();
	}

	#
	# Get ruv for each replica
	#
	for ($ridx = $myridx; $ridx <= $#allreplicas; $ridx++) {

		$replicaroot = $1 if ($allreplicas[$ridx] =~ /^\d+:([^:]*)/);
		# do a one level search with nsuniqueid in the filter - this will force the use of the
		# nsuniqueid index instead of the entry dn index, which seems to be unreliable in
		# heavily loaded servers
		$ruv = $conn->search($replicaroot, "one",
							 "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectClass=nsTombstone))",
							 0, qw(nsds50ruv nsruvReplicaLastModified));
		next if !$ruv; # this should be an error case . . .

		for ($ruv->getValues('nsds50ruv')) {
			if (m/\{replica\s+(\d+).+?\}\s*\S+\s*(\S+)/i) {
				$masterid = $1;
				$maxcsn = &to_decimal_csn ($2);
				$allruvs {"$ridx:$masterid"} = "$2:$maxcsn";
			}
		}

		for ($ruv->getValues('nsruvReplicaLastModified')) {
			if (m/\{replica\s+(\d+).+?\}\s*(\S+)/i) {
				$masterid = $1;
				$lastmodifiedat = hex($2);
				my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($lastmodifiedat);
				$mon++;
				$year += 1900;
				$hour = "0".$hour if ($hour < 10);
				$min = "0".$min if ($min < 10);
				$sec = "0".$sec if ($sec < 10);
				$allruvs {"$ridx:$masterid"} .= ";$mon/$mday/$year $hour:$min:$sec";
			}
		}
	}

	#
	# Get all agreements for each supplier replica
	#
	for ($ridx = $myridx; $ridx <= $#allreplicas; $ridx++) {
		$_ = $allreplicas[$ridx];

		# Skip consumers
		next if m/:consumer:/i;

		m/:([^:]*)$/;
		$replicadn = $1;
		my @attrlist = qw(cn nsds5BeginReplicaRefresh nsds5replicaUpdateInProgress
						  nsds5ReplicaLastInitStatus nsds5ReplicaLastInitStart
						  nsds5ReplicaLastInitEnd nsds5replicaReapActive
						  nsds5replicaLastUpdateStart nsds5replicaLastUpdateEnd
						  nsds5replicaChangesSentSinceStartup nsds5replicaLastUpdateStatus
						  nsds5ReplicaHost
						  nsds5ReplicaPort nsDS5ReplicaBindMethod nsds5ReplicaUpdateSchedule);
		$agreement = $conn->search("$replicadn", "sub", "(objectClass=nsDS5ReplicationAgreement)",
								   0, @attrlist);
		while ($agreement) {

			my %agmt = ();
			# Push consumer to server stack if we have not already
			$host = ($agreement->getValues('nsDS5ReplicaHost'))[0];
			$port = ($agreement->getValues('nsDS5ReplicaPort'))[0];
			$cidx = &add_server ("$host:$port");

			for (@attrlist) {
			  $agmt{$_} = ($agreement->getValues($_))[0];
			}
			if ($agmt{nsDS5ReplicaBindMethod} =~ /simple/i) {
			  $agmt{nsDS5ReplicaBindMethod} = 'n';
			}
			if (!$agmt{nsds5ReplicaUpdateSchedule} ||
			    ($agmt{nsds5ReplicaUpdateSchedule} eq '0000-2359 0123456') ||
			    ($agmt{nsds5ReplicaUpdateSchedule} eq '*') ||
			    ($agmt{nsds5ReplicaUpdateSchedule} eq '* *')) {
			  $agmt{nsds5ReplicaUpdateSchedule} = 'always in sync';
			}

			$agmt{ridx} = $ridx;
			$agmt{cidx} = $cidx;
			push @allagreements, \%agmt;

			$agreement = $conn->nextEntry ();
		}
	}

	$conn->close;
}

#
# Initially, the agreements have consumer host:port info instead of
# replica info. This routine will find the consumer replica info
#
sub find_consumer_replicas
{
	my ($m_ridx);		# index of master's replica
	my ($s_ridx);		# index of supplier's replica
	my ($c_ridx);		# index of consumer's replica
	my ($c_sidx);		# index of consumer server
	my ($remainder);	#
	my ($s_replicaroot);	# supplier replica root
	my ($c_replicaroot);	# consumer replica root
	my ($j, $val);

	#
	# Loop through every agreement defined on the current supplier replica
	#
	foreach (@allagreements) {
		$s_ridx = $_->{ridx};
		$c_sidx = $_->{cidx};
		$s_replicaroot = $1 if ($allreplicas[$s_ridx] =~ /^\d+:([^:]*)/);
		$c_replicaroot = "";

		# $c_ridx will be assigned to -$c_sidx
		# if the condumer is not accessible
		# $c_sidx will not be zero since it's
		# not the first server.
		$c_ridx = -$c_sidx;	# $c_sidx will not be zero

		# Loop through consumer's replicas and find
		# the counter part for the current supplier
		# replica
		for ($j = 0; $j <= $#allreplicas; $j++) {

			# Get a replica on consumer
	    	# I'm not sure what's going on here, but possibly could be made
			# much simpler with normalizeDN and/or ldap_explode_dn
			if ($allreplicas[$j] =~ /^$c_sidx:([^:]*)/) {
				$val = $1;

				# We need to find out the consumer
				# replica that matches the supplier
				# replicaroot most.
				if ($s_replicaroot =~ /^.*$val$/i &&
					length ($val) >= length ($c_replicaroot)) {
					$c_ridx = $j;

					# Avoid case-sensitive comparison
					last if (length($s_replicaroot) == length($val));
					$c_replicaroot = $val;
				}
			}
		}
		$_->{ridx} = $s_ridx;
		$_->{cidx} = $c_ridx;
	}
}

sub process_suppliers
{
	my ($ridx, $mid, $maxcsn);

	$mid = "";

	$last_sidx = -1;	# global variable for print html page

	for ($ridx = 0; $ridx <= $#allreplicas; $ridx++) {

		# Skip consumers and hubs
		next if $allreplicas[$ridx] !~ /:master:(\d+):/i;
		$mid = $1;

		# Skip replicas without agreements defined yet
		next if (! grep {$_->{ridx} == $ridx} @allagreements);

		$maxcsn = &print_master_header ($ridx, $mid);
		if ( "$maxcsn" != "none" ) {
			&print_consumer_header ();
			&print_consumers ($ridx, $mid);
		}
		&print_supplier_end;
	}

	if ($mid eq "") {
		print "<p>The server is not a master or it has no replication agreement\n";
	}
}

sub print_master_header
{
	my ($ridx, $mid) = @_;
	my ($myruv) = $allruvs {"$ridx:$mid"};
	my ($maxcsnval) = split ( /;/, "$myruv" );
	my ($maxcsn) = &to_string_csn ($maxcsnval);
	my ($sidx, $replicaroot, $replicatype, $serverid) = split (/:/, $allreplicas[$ridx]);

	# Print the master name
	if ( $last_sidx != $sidx ) {
		my ($ldapurl) = &get_ldap_url ($sidx, $sidx);
		&print_legend if ( $last_sidx < 0);
		print "<p><p><hr><p>\n";
		print "\n<p><center class=page-subtitle><font color=#0099cc>\n";
		print "Master:&nbsp $ldapurl</center>\n";
		$last_sidx = $sidx;
	}

	# Print the current replica info onthe master
	print "\n<p><table border=0 cellspacing=1 cellpadding=6 cols=10 width=100% class=bgColor9>\n";

	print "\n<tr><td colspan=10><center>\n";
	print "<font class=areatitle>Replica ID: </font>";
	print "<font class=text28>$serverid</font>\n";

	print "<font class=areatitle>Replica Root: </font>";
	print "<font class=text28>$replicaroot</font>\n";

	print "<font class=areatitle>Max CSN: </font>";
	print "<font class=text28>$maxcsn</font>\n";

	return $maxcsn;
}

sub print_consumer_header
{
	#Print the header of consumer
	print "\n<tr class=bgColor16>\n";
	print "<th nowrap>Receiver</th>\n";
	print "<th nowrap>Time Lag</th>\n";
	print "<th nowrap>Max CSN</th>\n";
	print "<th nowrap>Last Modify Time</th>\n";
	print "<th nowrap>Supplier</th>\n";
	print "<th nowrap>Sent/Skipped</th>\n";
	print "<th nowrap>Update Status</th>\n";
	print "<th nowrap>Update Started</th>\n";
	print "<th nowrap>Update Ended</th>\n";
	print "<th nowrap colspan=2>Schedule</th>\n";
	print "<th nowrap>SSL?</th>\n";
	print "</tr>\n";
}

sub print_consumers
{
	my ($m_ridx, $mid) = @_;
	my ($ignore, $m_replicaroot) = split (/:/, $allreplicas[$m_ridx]);
	my (@consumers, @ouragreements, @myagreements);
	my ($s_ridx, $c_ridx, $conntype, $schedule, $status);
	my ($c_maxcsn_str, $lag, $markcolor);
	my ($c_replicaroot, $c_replicatype);
	my ($first_entry);
	my ($nrows);
	my ($found);

	undef @ouragreements;

	# Collect all the consumer replicas for the current master replica
	push (@consumers, $m_ridx);
	foreach (@consumers) {
		$s_ridx = $_;
		for (@allagreements) {
			next if ($_->{ridx} != $s_ridx);
			$c_ridx = $_->{cidx};
			next if $c_ridx == $m_ridx;
			push @ouragreements, $_;
			$found = 0;
			foreach (@consumers) {
				if ($_ == $c_ridx) {
					$found = 1;
					last;
				}
			}
			push (@consumers, $c_ridx) if !$found;
		}
	}

	# Print each consumer replica
	my ($myruv) = $allruvs {"$m_ridx:$mid"};
	my ($m_maxcsn) = split ( /;/, "$myruv" );
	foreach (@consumers) {
		$c_ridx = $_;
		next if $c_ridx == $m_ridx;

		if ($c_ridx >= 0) {
			$myruv = $allruvs {"$c_ridx:$mid"};
			($c_maxcsn, $c_lastmodified) = split ( /;/, "$myruv" );
			($c_maxcsn_str, $lag, $markcolor) = &cacl_time_lag ($m_maxcsn, $c_maxcsn);
			$c_maxcsn_str =~ s/ /\<br\>/;
			($c_sidx, $c_replicaroot, $c_replicatype) = split (/:/, $allreplicas[$c_ridx]);
			$c_replicaroot = "same as master" if $m_replicaroot eq $c_replicaroot;
		}
		else {
			# $c_ridx is actually -$c_sidx when c is not available
			$c_sidx = -$c_ridx;
			$c_maxcsn_str = "_";
			$lag = "n/a";
			$markcolor = red;
			$c_replicaroot = "_";
			$c_replicatype = "_";
		}

		$nrows = 0;
		foreach (@ouragreements) {
			next if ($_->{cidx} != $c_ridx);
			$nrows++;
		}

		$first_entry = 1;
		foreach (@ouragreements) {
			next if ($_->{cidx} != $c_ridx);
			$s_ridx = $_->{ridx};
			$conntype = $_->{nsDS5ReplicaBindMethod};
			$status = $_->{nsds5replicaLastUpdateStatus};
			$schedule = $_->{nsds5ReplicaUpdateSchedule};
			$s_sidx = $1 if $allreplicas [$s_ridx] =~ /^(\d+):/;
			$s_ldapurl = &get_ldap_url ($s_sidx, "n/a");

			# Print out the consumer's replica and ruvs
			print "\n<tr class=bgColor13>\n";
			if ($first_entry) {
				$first_entry = 0;
				$c_ldapurl = &get_ldap_url ($c_sidx, $conntype);
				print "<td rowspan=$nrows width=5% class=bgColor5>$c_ldapurl<BR>Type: $c_replicatype</td>\n";
				print "<td rowspan=$nrows width=5% nowrap bgcolor=$markcolor><center>$lag</center></td>\n";
				print "<td rowspan=$nrows width=15% nowrap>$c_maxcsn_str</td>\n";
				print "<td rowspan=$nrows width=15% nowrap>$c_lastmodified</td>\n";
			}
			print "<td width=5% nowrap><center>$s_ldapurl</center></td>\n";
			my $changecount = $_->{nsds5replicaChangesSentSinceStartup};
			if ( $changecount =~ /^$mid:(\d+)\/(\d+) / || $changecount =~ / $mid:(\d+)\/(\d+) / ) {
				$changecount = "$1 / $2";
			}
			elsif ( $changecount =~ /^(\d+)$/ ) {
				$changecount = $changecount . " / " . "$_->{nsds5replicaChangesSkippedSinceStartup}";
			}
			else {
				$changecount = "0 / 0";
			}
			print "<td width=3% nowrap>$changecount</td>\n";       
			my $redfontstart = "";
			my $redfontend = "";
			if ($status =~ /error/i) {
			  $redfontstart = "<font color='red'>";
			  $redfontend = "</font>";
			}
			elsif ($status =~ /^(\d+) /) {
				if ( $1 != 0 ) {
					# warning
					$redfontstart = "<font color='#FF7777'>";
					$redfontend = "</font>";
				}
			}
			print "<td width=20% nowrap>$redfontstart$status$redfontend</td>\n";
			print "<td nowrap>", &format_z_time($_->{nsds5replicaLastUpdateStart}), "</td>\n";
			print "<td nowrap>", &format_z_time($_->{nsds5replicaLastUpdateEnd}), "</td>\n";
			if ( $schedule =~ /always/i ) {
				print "<td colspan=2 width=10% nowrap>$schedule</td>\n";
			}
			else {
				my ($ndays, @days);
				$schedule =~ /(\d\d)(\d\d)-(\d\d)(\d\d) (\d+)/;
				print "<td width=10% nowrap>$1:$2-$3:$4</td>\n";
				$ndays = $5;
				$ndays =~ s/(\d)/$1,/g;
				@days = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[eval $ndays];
				print "<td width=10% nowrap>@days</td>\n";
			}
			print "<td width=3% nowrap class=bgColor5>$conntype</td>\n";
		}
	}
}

sub cacl_time_lag
{
	my ($s_maxcsn, $c_maxcsn) = @_;
	my ($markcolor);
	my ($csn_str);
	my ($s_tm, $c_tm, $lag_tm, $lag_str, $hours, $minute);

	$csn_str = &to_string_csn ($c_maxcsn);

	if ($s_maxcsn && !$c_maxcsn) {
		$lag_str = "- ?:??:??";
		$markcolor = &get_color (36000); # assume consumer has big latency
	}
	elsif (!$s_maxcsn && $c_maxcsn) {
		$lag_str = "+ ?:??:??";
		$markcolor = &get_color (1); # consumer is ahead of supplier
	}
	elsif ($s_maxcsn le $c_maxcsn) {
		$lag_str = "0:00:00";
		$markcolor = &get_color (0);
	}
	else {
		my ($rawcsn, $decimalcsn) = split (/:/, $s_maxcsn);
		($s_tm) = split(/ /, $decimalcsn);

		($rawcsn, $decimalcsn) = split (/:/, $c_maxcsn);
		($c_tm) = split(/ /, $decimalcsn);
		if ($s_tm > $c_tm) {
			$lag_tm = $s_tm - $c_tm;
			$lag_str = "- ";
			$markcolor = &get_color ($lag_tm);
		}
		else {
			$lag_tm = $c_tm - $s_tm;
			$lag_str = "+ ";
			$markcolor = $allcolors{ $colorkeys[0] };	# no delay
		}
		$hours = int ($lag_tm / 3600);
		$lag_str .= "$hours:";

		$lag_tm = $lag_tm % 3600;
		$minutes = int ($lag_tm / 60);
		$minutes = "0".$minutes if ($minutes < 10);
		$lag_str .= "$minutes:";

		$lag_tm = $lag_tm % 60;
		$lag_tm = "0".$lag_tm if ($lag_tm < 10);
		$lag_str .= "$lag_tm";
	}
	return ($csn_str, $lag_str, $markcolor);
}

#
# The subroutine would append a new entry to the end of
# @servers if the host and port are new to @servers.
#
sub add_server
{
	my ($host, $port, $binddn, $bindpwd, $bindcert) = split (/:/, "@_");
	my ($shadowport) = $port;
	my ($domainpattern) = '\.[^:]+';
	my ($i);

	# Remove the domain name from the host name
	my ($hostnode) = $host;
	$hostnode = $1 if $host =~ /^(\w+)\./;

	# new host:port
	if ($binddn eq "" || $bindpwd eq "" && $bindcert eq "") {
		#
		# Look up connection parameter in the order of
		#	host:port
		#	host:*
		#	*:port
		#	*:*
		#
		my (@myconfig, $h, $p, $d, $w, $c);
		(@myconfig = grep (/^$hostnode($domainpattern)*:$port\D/i, @allconnections)) ||
		(@myconfig = grep (/^$hostnode($domainpattern)*:\*:/i, @allconnections)) ||
		(@myconfig = grep (/^\*:$port\D/, @allconnections)) ||
		(@myconfig = grep (/^\*:\*\D/, @allconnections));
		if ($#myconfig >= 0) {
			($h, $p, $d, $w, $c) = split (/:/, $myconfig[0]);
			($p, $shadowport) = split (/=/, $p);
			$p = "" if $p eq "*";
			$c = "" if $c eq "*";
		}
		if ($binddn eq "" || $binddn eq "*") {
			if ($d eq "" || $d eq "*") {
				$binddn = "cn=Directory Manager";
			}
			else {
				$binddn = $d;
			}
		}
		$bindpwd = $w if ($bindpwd eq "" || $bindpwd eq "*");
		$bindcert = $c if ($bindcert eq "" || $bindcert eq "*");
	}

	for ($i = 0; $i <= $#servers; $i++) {
		return $i if ($servers[$i] =~ /$hostnode($domainpattern)*:\d*=$shadowport\D/i);
	}

	push (@servers, "$host:$port=$shadowport:$binddn:$bindpwd:$bindcert");
	return $i;
}

sub get_ldap_url
{
	my ($sidx, $conntype) = @_;
	my ($host, $port) = split(/:/, $servers[$sidx]);
	my ($shadowport);
	($port, $shadowport) = split (/=/, $port);
	my ($protocol, $ldapurl);

	if ($port eq 636 && $conntype eq "0" || $conntype =~ /SSL/i) {
		$protocol = ldaps;
	}
	else {
		$protocol = ldap;
	}
	my ($instance) = $allaliases { "$host:$port" };
	$instance = "$host:$port" if !$instance;
	if ($conntype eq "n/a") {
		$ldapurl = $instance;
	}
	else {
		$ldapurl = "<a href=\"$protocol://$host:$port/\">$instance</a>";
	}
	return $ldapurl;
}

sub to_decimal_csn
{
	my ($maxcsn) = @_;
	if (!$maxcsn || $maxcsn eq "") {
		return "none";
	}

	my ($tm, $seq, $masterid, $subseq) = unpack("a8 a4 a4 a4", $maxcsn);

	$tm = hex($tm);
	$seq = hex($seq);
	$masterid = hex($masterid);
	$subseq = hex($subseq);

	return "$tm $seq $masterid $subseq";
}

sub to_string_csn
{
	my ($rawcsn, $decimalcsn) = split(/:/, "@_");
	if (!$rawcsn || $rawcsn eq "") {
		return "none";
	}
	my ($tm, $seq, $masterid, $subseq) = split(/ /, $decimalcsn);
	my ($sec, $min, $hour, $mday, $mon, $year) = localtime($tm);
	$mon++;
	$year += 1900;
	foreach ($sec, $min, $hour, $mday, $mon) {
		$_ = "0".$_ if ($_ < 10);
	}
	my ($csnstr) = "$mon/$mday/$year $hour:$min:$sec";
	$csnstr .= " $seq $subseq" if ( $seq != 0 || $subseq != 0 );
	return "$rawcsn ($csnstr)";
}

sub get_color
{
	my ($lag_minute) = @_;
	$lag_minute /= 60;
	my ($color) = $allcolors { $colorkeys[0] };
	foreach (@colorkeys) {
		last if ($lag_minute < $_);
		$color = $allcolors {$_};
	}
	return $color;
}

# subroutine to remove escaped encoding

sub unescape 
{
	#my ($_) = @_;
	tr/+/ /;
	s/%(..)/pack("c",hex($1))/ge;
	$_;
}

sub print_html_header
{
	# print the HTML header

	print "Content-type: text/html\n\n";
	print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"><html>\n";
	print "<head><title>Replication Status</title>\n";
	# print "<link type=text/css rel=stylesheet href=\"master-style.css\">\n";
	print "<style text/css>\n";
	print "Body, p, table, td, ul, li {color: #000000; font-family: Arial, Helvetica, sans-serif; font-size: 12px;}\n";
	print "A {color:blue; text-decoration: none;}\n";
	print "BODY {font-family: arial, helvetica, sans-serif}\n";
	print "P {font-family: arial, helvetica, sans-serif}\n";
	print "TH {font-weight: bold; font-family: arial, helvetica, sans-serif}\n";
	print "TD {font-family: arial, helvetica, sans-serif}\n";
	print ".bgColor1  {background-color: #003366;}\n";
	print ".bgColor4  {background-color: #cccccc;}\n";
	print ".bgColor5  {background-color: #999999;}\n";
	print ".bgColor9  {background-color: #336699;}\n";
	print ".bgColor13 {background-color: #ffffff;}\n";
	print ".bgColor16 {background-color: #6699cc;}\n";
	print ".text8  {color: #0099cc; font-size: 11px; font-weight: bold;}\n";
	print ".text28 {color: #ffcc33; font-size: 12px; font-weight: bold;}\n";
	print ".areatitle {font-weight: bold; color: #ffffff; font-family: arial, helvetica, sans-serif}\n";
	print ".page-title {font-weight: bold; font-size: larger; font-family: arial, helvetica, sans-serif}\n";
	print ".page-subtitle {font-weight: bold; font-family: arial, helvetica, sans-serif}\n";

	print "</style></head>\n<body class=bgColor4>\n";

	if ($opt_u) {
		print "<meta http-equiv=refresh content=$interval; URL=$opt_u>\n";
	}

	print "<table border=0 cellspacing=0 cellpadding=10 width=100% class=bgColor1>\n";
	print "<tr><td><font class=text8>$now</font></td>\n";
	print "<td align=center class=page-title><font color=#0099CC>";
	print "Directory Server Replication Status</font>\n";

	if ($opt_u) {
		print "<br><font class=text8>(This page updates every $interval seconds)</font>\n";
	}

	print "</td><td align=right valign=center width=25%><font class=text8>$version";
	print "</font></td></table>\n";
}

sub print_legend
{
	my ($nlegends) = $#colorkeys + 1;
	print "\n<center><p><font class=page-subtitle color=#0099cc>Time Lag Legend:</font><p>\n";
	print "<table cellpadding=6 cols=$nlegends width=40%>\n<tr>\n";
	my ($i, $j);
	for ($i = 0; $i < $nlegends - 1; $i++) {
		$j = $colorkeys[$i];
		print "\n<td bgcolor=$allcolors{$j}><center>within $colorkeys[$i+1] min</center></td>\n";
	}
	$j = $colorkeys[$i];
	print "\n<td bgcolor=$allcolors{$j}><center>over $colorkeys[$i] min</center></td>\n";
	print "\n<td bgcolor=red><center>server n/a</center></td>\n";
	print "</table></center>\n";
}

sub print_supplier_end
{
	print "</table>\n";
}

# given a string in generalized time format, convert to ascii time
sub format_z_time
{
  my $zstr = shift;
  return "n/a" if (! $zstr);
  my ($year, $mon, $day, $hour, $min, $sec) =
	($zstr =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
  my $time = timegm($sec, $min, $hour, $day, ($mon-1), $year);
  ($sec, $min, $hour, $day, $mon, $year) = localtime($time);
  $mon++;
  $year += 1900;
  foreach ($sec, $min, $hour, $day, $mon) {
	$_ = "0".$_ if ($_ < 10);
  }

  return "$mon/$day/$year $hour:$min:$sec";
}


--- NEW FILE template-verify-db.pl.in ---
#{{PERL-EXEC}}
#
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
# 
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# 
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception. 
# 
# 
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#

sub getDbDir
{
    (my $here) = @_;
    my @dbdirs = ();

    opendir(DIR, $here) or die "can't opendir $here : $!";
    while (defined($dir = readdir(DIR)))
    {
        my $thisdir;
        if ("$here" eq ".")
        {
            $thisdir = $dir;
        }
        else
        {
            $thisdir = $here . "{{SEP}}" . $dir;
        }
        if (-d $thisdir)
        {
            if (!($thisdir =~ /\./))
            {
                opendir(SUBDIR, "$thisdir") or die "can't opendir $thisdir : $!";
                while (defined($file = readdir(SUBDIR)))
                {
                    if ($file eq "DBVERSION")
                    {
                        $#dbdirs++;
                        $dbdirs[$#dbdirs] = $thisdir;
                    }
                }
                closedir(SUBDIR);
            }
        }
    }
    closedir(DIR);

    return \@dbdirs;
}

sub getLastLogfile
{
    (my $here) = @_;
    my $logfile = "";

    opendir(DIR, $here) or die "can't opendir $here : $!";
    while (defined($file = readdir(DIR)))
    {
        if ($file =~ /log./)
        {
            $logfile = $file;
        }
    }
    closedir(DIR);

    return \$logfile;
}

$isWin = -d '\\';
if ($isWin) {
	$NULL = "nul";
} else {
	$NULL = "/dev/null";
}

print("*****************************************************************\n");
print("verify-db: This tool should only be run if recovery start fails\n" .
      "and the server is down.  If you run this tool while the server is\n" .
      "running, you may get false reports of corrupted files or other\n" .
      "false errors.\n");
print("*****************************************************************\n");

# get dirs having DBVERSION
my $dbdirs = getDbDir(".");
my $brand_ds = {{DS-BRAND}};
my $prefix = "{{DS-ROOT}}";

$ENV{'PATH'} = '$prefix at db_bindir@:$prefix/usr/lib:@db_bindir@:/usr/lib';
$ENV{'LD_LIBRARY_PATH'} = '@db_libdir@:/usr/lib';
$ENV{'SHLIB_PATH'} = '@db_libdir@:/usr/lib';

for (my $i = 0; $i < @$dbdirs; $i++)
{
    # run db_printlog -h <dbdir> for each <dbdir>
    print "Verify log files in $$dbdirs[$i] ... ";
    open(PRINTLOG, "db_printlog -h $$dbdirs[$i] 2>&1 1> $NULL |");
    sleep 1;
    my $haserr = 0;
    while ($l = <PRINTLOG>)
    {
        if ("$l" ne "")
        {
            if ($haserr == 0)
            {
                print "\n";
            }
            print "LOG ERROR: $l";
            $haserr++;
        }
    }
    close(PRINTLOG);
    if ($haserr == 0 && $? == 0)
    {
        print "Good\n";
    }
    else
    {
        my $logfile = getLastLogfile($$dbdirs[$i]);
        print "Log file(s) in $$dbdirs[$i] could be corrupted.\n";
        print "Please delete a log file $$logfile, and try restarting the server.\n";
    }
}

for (my $i = 0; $i < @$dbdirs; $i++)
{
    # changelog
    opendir(DB, $$dbdirs[$i]) or die "can't opendir $$dbdirs[$i] : $!";
    while (defined($db = readdir(DB)))
    {
        if ($db =~ /\.db/)
        {
            my $thisdb = $$dbdirs[$i] . "{{SEP}}" . $db;
            print "Verify $thisdb ... ";
            open(DBVERIFY, "db_verify $thisdb 2>&1 1> $NULL |");
            sleep 1;
            my $haserr = 0;
            while ($l = <DBVERIFY>)
            {
                if ($haserr == 0)
                {
                    print "\n";
                }
                if ("$l" ne "")
                {
                    $haserr++;
                    print "DB ERROR: $l";
                }
            }
            close(DBVERIFY);
            if ($haserr == 0 && $? == 0)
            {
                print "Good\n";
            }
            else
            {
                print "changelog file $db in $$dbdirs[$i] is corrupted.\n";
                print "Please restore your backup and recover the database.\n";
            }
        }
    }
    closedir(DB);

    # backend: get instance dirs under <dbdir>
    my $instdirs = getDbDir($$dbdirs[$i]);

    for (my $j = 0; $j < @$instdirs; $j++)
    {
        opendir(DIR, $$instdirs[$j]) or die "can't opendir $here : $!";
        while (defined($db = readdir(DIR)))
        {
            if ($db =~ /\.db/)
            {
                my $thisdb = $$instdirs[$j] . "{{SEP}}" . $db;
                print "Verify $thisdb ... ";
                open(DBVERIFY, "db_verify $thisdb 2>&1 1> $NULL |");
                sleep 1;
                my $haserr = 0;
                while ($l = <DBVERIFY>)
                {
                    if ($haserr == 0)
                    {
                        print "\n";
                    }
                    if ("$l" ne "")
                    {
                        $haserr++;
                        print "DB ERROR: $l";
                    }
                }
                close(DBVERIFY);
                if ($haserr == 0 && $? == 0)
                {
                    print "Good\n";
                }
                else
                {
                    if ("$db" =~ /id2entry.db/)
                    {
                        print "Primary db file $db in $$instdirs[$j] is corrupted.\n";
                        print "Please restore your backup and recover the database.\n";
                    }
                    else
                    {
                        print "Secondary index file $db in $$instdirs[$j] is corrupted.\n";
                        print "Please run db2index(.pl) for reindexing.\n";
                    }
                }
            }
        }
        closedir(DIR);
    }
}


Index: template-cl-dump.pl
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/admin/src/scripts/template-cl-dump.pl,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- template-cl-dump.pl	25 Oct 2006 00:04:42 -0000	1.8
+++ template-cl-dump.pl	25 Oct 2006 20:36:46 -0000	1.9
@@ -99,6 +99,8 @@
 # enable the use of our bundled perldap with our bundled ldapsdk libraries
 # all of this nonsense can be omitted if the mozldapsdk and perldap are
 # installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5)
+$prefix = "{{DS-ROOT}}";
+
 $ENV{'LD_LIBRARY_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';
 $ENV{'SHLIB_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';
 


Index: template-ns-newpwpolicy.pl
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/admin/src/scripts/template-ns-newpwpolicy.pl,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- template-ns-newpwpolicy.pl	25 Oct 2006 00:04:42 -0000	1.6
+++ template-ns-newpwpolicy.pl	25 Oct 2006 20:36:46 -0000	1.7
@@ -42,6 +42,8 @@
 # enable the use of our bundled perldap with our bundled ldapsdk libraries
 # all of this nonsense can be omitted if the mozldapsdk and perldap are
 # installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5)
+$prefix = "{{DS-ROOT}}";
+
 $ENV{'PATH'} = '$prefix/usr/lib/mozldap6:$prefix/usr/lib:/usr/lib/mozldap6:/usr/lib';
 $ENV{'LD_LIBRARY_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';
 $ENV{'SHLIB_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';
@@ -64,12 +66,6 @@
 $opt_h = "{{SERVER-NAME}}";
 $opt_v = 0;
 
-$ENV{'PATH'} = '$prefix{{SEP}}usr{{SEP}}lib:{{SEP}}usr{{SEP}}lib{{SEP}}mozldap';
-$ENV{'LD_LIBRARY_PATH'} .= ":";
-$ENV{'LD_LIBRARY_PATH'} .= "$prefix{{SEP}}usr{{SEP}}lib:{{SEP}}usr{{SEP}}lib{{SEP}}mozldap";
-$ENV{'SHLIB_PATH'} .= ":";
-$ENV{'SHLIB_PATH'} .= "$prefix{{SEP}}usr{{SEP}}lib:{{SEP}}usr{{SEP}}lib{{SEP}}mozldap";
-
 # Variables
 $ldapsearch="ldapsearch -1";
 $ldapmodify="ldapmodify";


Index: template-repl-monitor-cgi.pl
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/admin/src/scripts/template-repl-monitor-cgi.pl,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- template-repl-monitor-cgi.pl	25 Oct 2006 00:04:42 -0000	1.6
+++ template-repl-monitor-cgi.pl	25 Oct 2006 20:36:46 -0000	1.7
@@ -56,6 +56,8 @@
 	$params .= " -u \"$admurl\"";
 }
 $siteroot = $cgiVars{'siteroot'};
+$prefix = "{{DS-ROOT}}";
+
 $ENV{'PATH'} = '$prefix/usr/lib/mozldap6:$prefix/usr/lib:/usr/lib/mozldap6:/usr/lib';
 $ENV{'LD_LIBRARY_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';
 $ENV{'SHLIB_PATH'} = '$prefix/usr/lib/dirsec:$prefix/usr/lib:/usr/lib/dirsec:/usr/lib';


Index: template-verify-db.pl
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/admin/src/scripts/template-verify-db.pl,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- template-verify-db.pl	25 Oct 2006 00:04:42 -0000	1.6
+++ template-verify-db.pl	25 Oct 2006 20:36:46 -0000	1.7
@@ -112,6 +112,8 @@
 # get dirs having DBVERSION
 my $dbdirs = getDbDir(".");
 my $brand_ds = {{DS-BRAND}};
+my $prefix = "{{DS-ROOT}}";
+
 $ENV{'PATH'} = '$prefix/usr/bin:$prefix/usr/lib:/usr/bin:/usr/lib';
 $ENV{'LD_LIBRARY_PATH'} = ':/usr/lib';
 $ENV{'SHLIB_PATH'} = ':/usr/lib';




More information about the Fedora-directory-commits mailing list