#!/usr/bin/perl
#
# --- 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright (C) 2007 Red Hat, Inc.
# All rights reserved.
# --- END COPYRIGHT BLOCK ---
#

##############################################################
# This script is used to create a new instance of a
# subsystem within a PKI installation.
#
# Sample Invocation (for CA):
#
#    ./pkicreate -pki_instance_root=/var/lib
#                -pki_instance_name=pki-ca
#                -subsystem_type=ca
#                -agent_secure_port=9443
#                -ee_secure_port=9444
#                -ee_secure_client_auth_port=9446
#                -admin_secure_port=9445
#                -unsecure_port=9180
#                -tomcat_server_port=9701
#                -user=pkiuser
#                -group=pkiuser
#                -redirect conf=/etc/pki-ca
#                -redirect logs=/var/log/pki-ca
#                -verbose
#
##############################################################


##############################################################
# Perl Version
##############################################################

my $MINIMUM_PERL_VERSION = "5.006001";

my $perl_version_error_message = "ERROR:  Using Perl version $] ...\n"
                               . "        Must use Perl version "
                               . "$MINIMUM_PERL_VERSION or later to "
                               . "run this script!\n";

die "$perl_version_error_message" if $] < $MINIMUM_PERL_VERSION;


##############################################################
# Execution Check
##############################################################

# Disallow 'others' the ability to 'write' to new files
umask 00002;

# Check to insure that this script's original
# invocation directory has not been deleted!
my $cwd = `/bin/pwd`;
chomp $cwd;
if( "$cwd" eq "" ) {
    print( STDERR "Cannot invoke '$0' from non-existent directory!\n" );
    print( STDOUT "\n" );
    exit 255;
}


##############################################################
# Environment Variables
##############################################################

# option to not run this script.
if( defined( $ENV{ 'DONT_RUN_PKICREATE' } ) ) {
    if( $ENV{ 'DONT_RUN_PKICREATE' } == 1 ) {
        print( STDERR "Env. variable DONT_RUN_PKICREATE is set. Exiting.\n" );
        print( STDOUT "\n" );
        exit 0;
    }
}

# additional option to not run this script on Solaris
# (unfortunately, pkgadd doesn't process all environment variables)
if( $^O eq "solaris" ) {
    if( -f "/tmp/DONT_RUN_PKICREATE" ) {
        print( STDERR "File DONT_RUN_PKICREATE exists. Exiting.\n" );
        print( STDOUT "\n" );
        exit 0;
    }
}

# untaint called subroutines
if( ( $^O ne 'Windows_NT' ) && ( $^O ne 'MSWin32' ) ) {
    $> = $<;   # set effective user ID to real UID
    $) = $(;   # set effective group ID to real GID
    $ENV{ 'PATH' } = '/bin:/usr/bin';
    $ENV{ 'ENV' } = '' if $ENV{ 'ENV' } ne '';
}


##############################################################
# Command-Line Variables
##############################################################

my $ARGS = ( $#ARGV + 1 );


##############################################################
# Shared Common Perl Data and Subroutines
##############################################################

# Compute "flavor" of Operating System
my $pki_flavor = "";
if( $^O eq "linux" ) {
    $pki_flavor = "pki";
} elsif( $^O eq "solaris" ) {
    $pki_flavor = "pki";
} else {
    print( STDERR
           "ERROR:  Unsupported platform '$^O'!\n" );
    print( STDOUT "\n" );
    exit 255;
}

$pki_flavor =~ s/\s+$//g;

# Establish path to scripts
my $pki_subsystem_common_area = "/usr/share/$pki_flavor";
my $common_path = "/usr/share/$pki_flavor/scripts";

if( ! -d "$common_path" ) {
    print( STDERR
           "ERROR:  The path '$common_path' does not exist!\n"
         . "        Unable to load shared Common Perl Data "
         . "and Subroutines!\n" );
    print( STDOUT "\n" );
    exit 255;
}

if( ! -e "$common_path/pkicommon" ) {
    print( STDERR
           "ERROR:  The file '$common_path/pkicommon' does not exist!\n"
         . "        Unable to load shared Common Perl Data "
         . "and Subroutines!\n" );
    print( STDOUT "\n" );
    exit 255;
}

eval( "use lib '" . $common_path . "'" );
require( 'pkicommon' );

# make -w happy by suppressing warnings of Global variables used only once
my $suppress = "";
$suppress = $hostname;
$suppress = $obj_ext;
$suppress = $tmp_dir;
$suppress = $default_security_libraries;
$suppress = $default_system_libraries;
$suppress = $lib_prefix;
$suppress = $default_system_user_binaries;


##############################################################
# Local Constants
##############################################################

# Script used to complete setting up the PKI framework
my $pkicomplete = "$pki_subsystem_common_area/scripts/pkicomplete";

# Links created via initial "tomcat" installation that MUST be removed!!!
my $jdbc_stdext_link = "/var/lib/tomcat5/common/lib/\[jdbc-stdext\].jar";
my $jndi_link        = "/var/lib/tomcat5/common/lib/\[jndi\].jar";
my $jaas_link        = "/var/lib/tomcat5/server/lib/\[jaas\].jar";

# Base subsystem directory names
my $acl_base_subsystem_dir      = "acl";       # CA, KRA, OCSP, TKS
my $alias_base_subsystem_dir    = "alias";     # CA, KRA, OCSP, TKS, RA, TPS
my $applets_base_subsystem_dir  = "applets";   # TPS
my $cgibin_base_subsystem_dir   = "cgi-bin";   # TPS (Apache)
my $conf_base_subsystem_dir     = "conf";      # CA, KRA, OCSP, TKS, RA, TPS
my $docroot_base_subsystem_dir  = "docroot";   # RA, TPS (Apache)
my $emails_base_subsystem_dir   = "emails";    # CA
my $etc_base_subsystem_dir      = "etc";       # CA, KRA, OCSP, TKS, RA, TPS
my $lib_base_subsystem_dir      = "lib";       # RA, TPS
my $logs_base_subsystem_dir     = "logs";      # CA, KRA, OCSP, TKS, RA, TPS
my $profiles_base_subsystem_dir = "profiles";  # CA, KRA, OCSP, TKS
my $samples_base_subsystem_dir  = "samples";   # TPS
my $scripts_base_subsystem_dir  = "scripts";   # RA, TPS
my $shared_base_subsystem_dir   = "shared";    # CA, KRA, OCSP, TKS (Tomcat)
my $temp_base_subsystem_dir     = "temp";      # CA, KRA, OCSP, TKS (Tomcat)
my $webapps_base_subsystem_dir  = "webapps";   # CA, KRA, OCSP, TKS
my $work_base_subsystem_dir     = "work";      # CA, KRA, OCSP, TKS (Tomcat)

# Base instance directory names
my $acl_base_instance_dir      = "acl";       # CA, KRA, OCSP, TKS
my $alias_base_instance_dir    = "alias";     # CA, KRA, OCSP, TKS, RA, TPS
my $bin_base_instance_dir      = "bin";       # TPS
my $cgibin_base_instance_dir   = "cgi-bin";   # TPS (Apache)
my $conf_base_instance_dir     = "conf";      # CA, KRA, OCSP, TKS, RA, TPS
my $docroot_base_instance_dir  = "docroot";   # RA, TPS (Apache)
my $emails_base_instance_dir   = "emails";    # CA
my $lib_base_instance_dir      = "lib";       # RA, TPS
my $logs_base_instance_dir     = "logs";      # CA, KRA, OCSP, TKS, RA, TPS
my $profiles_base_instance_dir = "profiles";  # CA, KRA, OCSP, TKS
my $scripts_base_instance_dir  = "scripts";   # RA, TPS
my $shared_base_instance_dir   = "shared";    # CA, KRA, OCSP, TKS (Tomcat)
my $temp_base_instance_dir     = "temp";      # CA, KRA, OCSP, TKS (Tomcat)
my $webapps_base_instance_dir  = "webapps";   # CA, KRA, OCSP, TKS
my $work_base_instance_dir     = "work";      # CA, KRA, OCSP, TKS (Tomcat)

# Base instance symbolic link names
my $common_base_instance_symlink  = "common";   # CA, KRA, OCSP, TKS
my $conf_base_instance_symlink    = "conf";     # CA, KRA, OCSP, TKS, RA, TPS
my $logs_base_instance_symlink    = "logs";     # CA, KRA, OCSP, TKS, RA, TPS
my $run_base_instance_symlink     = "run";      # RA, TPS

# Base names
my $cgi_home_base_name           = "home/index.cgi";       # TPS
my $cgi_demo_base_name           = "demo/index.cgi";       # TPS
my $cgi_so_base_name             = "so/index.cgi";         # TPS
my $cgi_so_enroll_name           = "so/enroll.cgi";        # TPS
my $cgi_sow_dir_name             = "sow";                  # TPS
my $cgi_sow_cfg_pl_name          = "sow/cfg.pl";           # TPS
my $addAgents_ldif_base_name     = "addAgents.ldif";       # TPS
my $addIndexes_ldif_base_name    = "addIndexes.ldif";      # TPS
my $addTokens_ldif_base_name     = "addTokens.ldif";       # TPS
my $addVLVIndexes_ldif_base_name = "addVLVIndexes.ldif";   # TPS
my $apachectl_base_name          = "apachectl";            # TPS
my $nss_pcache_base_name         = "nss_pcache";           # RA, TPS
my $catalina_sh_base_name        = "dtomcat5";             # CA, KRA, OCSP, TKS
my $certsrv_jar_base_name        = "certsrv.jar";          # CA, KRA, OCSP, TKS
my $nsutil_jar_base_name         = "nsutil.jar";           # CA, KRA, OCSP, TKS
my $cmsutil_jar_base_name        = "cmsutil.jar";          # CA, KRA, OCSP, TKS
my $cms_jar_base_name            = "cms.jar";              # CA, KRA, OCSP, TKS
my $cmsbundle_jar_base_name      = "cmsbundle.jar";        # CA, KRA, OCSP, TKS
my $cmscore_jar_base_name        = "cmscore.jar";          # CA, KRA, OCSP, TKS
my $conf_base_name               = "conf";                 # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $httpd_conf_base_name         = "httpd.conf";           # RA, TPS
my $index_html_base_name         = "index.html";           # CA, KRA, OCSP, TKS
my $logs_base_name               = "logs";                 # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $magic_base_name              = "magic";                # RA, TPS
my $mime_types_base_name         = "mime.types";           # RA, TPS
my $noise_base_name              = "noise";                # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $nss_conf_base_name           = "nss.conf";             # RA, TPS
my $perl_conf_base_name          = "perl.conf";            # RA, TPS
my $osutil_jar_base_name         = "osutil.jar";           # CA, KRA, OCSP, TKS
my $password_conf_base_name      = "password.conf";        # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $pfile_base_name              = "pfile";                # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $pwcache_conf_base_name       = "pwcache.conf";         # RA, TPS
my $pki_cfg_base_name            = "CS.cfg";               # CA, KRA, OCSP, TKS,
                                                           # RA, TPS
my $schemaMods_ldif_base_name    = "schemaMods.ldif";      # RA, TPS
my $server_xml_base_name         = "server.xml";           # CA, KRA, OCSP, TKS
my $servercertnick_conf_base_name         = "serverCertNick.conf";           # CA, KRA, OCSP, TKS
my $tomcat5_conf_base_name       = "tomcat5.conf";         # CA, KRA, OCSP, TKS
my $velocity_prop_base_name      = "velocity.properties";  # CA, KRA, OCSP, TKS
my $web_xml_base_name            = "web.xml";              # CA, KRA, OCSP, TKS
my $profile_select_base_name     = "ProfileSelect.template"; #CA

# Subdirectory names
my $perl_base_instance_symlink      = "perl";        # RA, TPS
my $perl_base_subsystem_dir         = "perl";        # RA, TPS
my $signed_audit_base_instance_dir  = "signedAudit"; # CA, KRA, OCSP, TKS, TPS
my $webapps_root_base_instance_dir  = "ROOT";        # CA, KRA, OCSP, TKS
my $webapps_root_base_subsystem_dir = "ROOT";        # CA, KRA, OCSP, TKS
my $webinf_base_instance_dir        = "WEB-INF";     # CA, KRA, OCSP, TKS

# Defaults
my $default_apache_pids_path       = "/var/run/pki";
my $default_java_path              = "/usr/share/java";
my $default_dir_permissions        = 00770;
my $default_exe_permissions        = 00770;
my $default_file_permissions       = 00660;
my $default_security_token         = "internal";
my $default_tomcat_common_path     = "/var/lib/tomcat5/common";

# Default PKI user and group to give to PKI installed files
my $pki_user  = $PKI_USER;
my $pki_group = $PKI_GROUP;

# PKI creation constants
my $db_password_low  = 100000000000;
my $db_password_high = 999999999999;

# Template slot constants (RA, TPS)
my $GROUPID                = "GROUPID";
my $HTTPD_CONF             = "HTTPD_CONF";
my $INSTANCE_ID            = "INSTANCE_ID";
my $INSTANCE_ROOT          = "INSTANCE_ROOT";
my $LIB_PREFIX             = "LIB_PREFIX";
my $NSS_CONF               = "NSS_CONF";
my $OBJ_EXT                = "OBJ_EXT";
my $PORT                   = "PORT";
my $PROCESS_ID             = "PROCESS_ID";
my $SECURE_PORT            = "SECURE_PORT";
my $NON_CLIENTAUTH_SECURE_PORT = "NON_CLIENTAUTH_SECURE_PORT";
my $SECURITY_LIBRARIES     = "SECURITY_LIBRARIES";
my $SERVER_NAME            = "SERVER_NAME";
my $SERVER_ROOT            = "SERVER_ROOT";
my $SUBSYSTEM_TYPE         = "SUBSYSTEM_TYPE";
my $SYSTEM_LIBRARIES       = "SYSTEM_LIBRARIES";
my $SYSTEM_USER_LIBRARIES  = "SYSTEM_USER_LIBRARIES";
my $TMP_DIR                = "TMP_DIR";
my $TPS_DIR                = "TPS_DIR";
my $USERID                 = "USERID";
my $FORTITUDE_APACHE       = "FORTITUDE_APACHE";
my $FORTITUDE_DIR          = "FORTITUDE_DIR";
my $FORTITUDE_MODULE       = "FORTITUDE_MODULE";
my $FORTITUDE_LIB_DIR      = "FORTITUDE_LIB_DIR";
my $FORTITUDE_AUTH_MODULES = "FORTITUDE_AUTH_MODULES";
my $FORTITUDE_NSS_MODULES  = "FORTITUDE_NSS_MODULES";
my $REQUIRE_CFG_PL         = "REQUIRE_CFG_PL";

# Template slot constants (CA, KRA, OCSP, TKS)
my $INSTALL_TIME              = "INSTALL_TIME";
my $PKI_AGENT_CLIENTAUTH_SLOT = "PKI_AGENT_CLIENTAUTH";
my $PKI_CERT_DB_PASSWORD_SLOT = "PKI_CERT_DB_PASSWORD";
my $PKI_CFG_PATH_NAME_SLOT    = "PKI_CFG_PATH_NAME";
my $PKI_GROUP_SLOT            = "PKI_GROUP";
my $PKI_INSTANCE_ID_SLOT      = "PKI_INSTANCE_ID";
my $PKI_INSTANCE_PATH_SLOT    = "PKI_INSTANCE_PATH";
my $PKI_INSTANCE_ROOT_SLOT    = "PKI_INSTANCE_ROOT";
my $PKI_MACHINE_NAME_SLOT     = "PKI_MACHINE_NAME";
my $PKI_RANDOM_NUMBER_SLOT    = "PKI_RANDOM_NUMBER";
my $PKI_SECURE_PORT_SLOT      = "PKI_SECURE_PORT";
my $PKI_EE_SECURE_PORT_SLOT   = "PKI_EE_SECURE_PORT";
my $PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT   = "PKI_EE_SECURE_CLIENT_AUTH_PORT";
my $PKI_AGENT_SECURE_PORT_SLOT = "PKI_AGENT_SECURE_PORT";
my $PKI_ADMIN_SECURE_PORT_SLOT = "PKI_ADMIN_SECURE_PORT";
my $PKI_SERVER_XML_CONF       = "PKI_SERVER_XML_CONF";
my $PKI_SUBSYSTEM_TYPE_SLOT   = "PKI_SUBSYSTEM_TYPE";
my $PKI_UNSECURE_PORT_SLOT    = "PKI_UNSECURE_PORT";
my $PKI_USER_SLOT             = "PKI_USER";
my $TOMCAT_SERVER_PORT_SLOT   = "TOMCAT_SERVER_PORT";
my $PKI_FLAVOR_SLOT           = "PKI_FLAVOR";
my $PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT     = "PKI_UNSECURE_PORT_CONNECTOR_NAME";
my $PKI_SECURE_PORT_CONNECTOR_NAME_SLOT       = "PKI_SECURE_PORT_CONNECTOR_NAME";
my $PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT = "PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME";
my $PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT    = "PKI_EE_SECURE_PORT_CONNECTOR_NAME";
my $PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT    = "PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME";
my $PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT     = "PKI_UNSECURE_PORT_SERVER_COMMENT";
my $PKI_SECURE_PORT_COMMENT_SERVER_SLOT       = "PKI_SECURE_PORT_SERVER_COMMENT";
my $PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT = "PKI_ADMIN_SECURE_PORT_SERVER_COMMENT";
my $PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT    = "PKI_EE_SECURE_PORT_SERVER_COMMENT";
my $PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT = "PKI_EE_SECURE_CLIENT_AUTH_PORT_SERVER_COMMENT";
my $PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT  = "PKI_OPEN_SEPARATE_PORTS_SERVER_COMMENT";
my $PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT = "PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT";
my $PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT  = "PKI_OPEN_SEPARATE_PORTS_WEB_COMMENT";
my $PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT = "PKI_CLOSE_SEPARATE_PORTS_WEB_COMMENT";
my $PKI_UNSECURE_PORT_NAME      = "Unsecure";
my $PKI_AGENT_SECURE_PORT_NAME  = "Agent";
my $PKI_ADMIN_SECURE_PORT_NAME  = "Admin";
my $PKI_EE_SECURE_PORT_NAME     = "EE";
my $PKI_EE_SECURE_CLIENT_AUTH_PORT_NAME     = "EEClientAuth";
my $PKI_SECURE_PORT_NAME        = "Secure";
my $PKI_UNUSED_SECURE_PORT_NAME = "Unused";
my $PKI_UNSECURE_SEPARATE_PORTS_COMMENT = "<!-- Port Separation:  Unsecure Port Connector -->";
my $PKI_AGENT_SECURE_SEPARATE_PORTS_COMMENT = "<!-- Port Separation:  Agent Secure Port Connector -->";
my $PKI_ADMIN_SECURE_SEPARATE_PORTS_COMMENT = "<!-- Port Separation:  Admin Secure Port Connector -->";
my $PKI_EE_SECURE_SEPARATE_PORTS_COMMENT = "<!-- Port Separation:  EE Secure Port Connector -->";
my $PKI_EE_SECURE_CLIENT_AUTH_SEPARATE_PORTS_COMMENT = "<!-- Port Separation:  EE Secure Client Auth Port Connector -->";
my $PKI_UNSECURE_SHARED_PORTS_COMMENT = "<!-- Shared Ports:  Unsecure Port Connector -->";
my $PKI_SECURE_SHARED_PORTS_COMMENT = "<!-- Shared Ports:  Agent, EE, and Admin Secure Port Connector -->";
my $PKI_OPEN_COMMENT          = "<!--";
my $PKI_CLOSE_COMMENT         = "-->";
my $PKI_WEBAPPS_NAME         = "PKI_WEBAPPS_NAME";

# PKI removal constants
my $saved_cleanup_file_name = ".cleanup.dat";
my $saved_file_marker       = "[files]";
my $saved_directory_marker  = "[directories]";

#selinux constants
my $semanage = "/usr/sbin/semanage";
my $restorecon = "/sbin/restorecon";
my $SELINUX_PORT_UNDEFINED = 0;
my $SELINUX_PORT_DEFINED = 1;
my $SELINUX_PORT_WRONGLY_DEFINED = 2;

##############################################################
# Local Data Structures
##############################################################

# Useful pki references
@installed_files = ();
@installed_stray_directories = ();

%redirects = ();

my %selinux_ports = ();


##############################################################
# Local Variables
##############################################################

# Command-line variables (mandatory)
my $pki_instance_root  = "";
my $pki_instance_name  = "";
my $subsystem_type     = "";
my $secure_port        = -1;
my $non_clientauth_secure_port = -1;
my $unsecure_port      = -1;
my $tomcat_server_port = -1;

# Command-line variables (optional)
my $agent_secure_port    = -1;
my $ee_secure_port       = -1;
my $ee_secure_client_auth_port = -1;
my $admin_secure_port    = -1;
my $username             = "";
my $groupname            = "";
my $redirected_conf_path = "";
my $redirected_logs_path = "";

# Base subsystem directory paths
my $pki_subsystem_path      = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $acl_subsystem_path      = "";  # CA, KRA, OCSP, TKS
my $alias_subsystem_path    = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $applets_subsystem_path  = "";  # TPS
my $bin_subsystem_path      = "";  # TPS
my $cgibin_subsystem_path   = "";  # TPS (Apache)
my $conf_subsystem_path     = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $docroot_subsystem_path  = "";  # RA, TPS (Apache)
my $emails_subsystem_path   = "";  # CA
my $etc_subsystem_path      = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $lib_subsystem_path      = "";  # RA, TPS
my $logs_subsystem_path     = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $profiles_subsystem_path = "";  # CA, KRA, OCSP, TKS
my $samples_subsystem_path  = "";  # TPS
my $scripts_subsystem_path  = "";  # RA, TPS
my $shared_subsystem_path   = "";  # CA, KRA, OCSP, TKS (Tomcat)
my $temp_subsystem_path     = "";  # CA, KRA, OCSP, TKS (Tomcat)
my $webapps_subsystem_path  = "";  # CA, KRA, OCSP, TKS
my $common_ui_subsystem_path = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $ui_subsystem_path       = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $work_subsystem_path     = "";  # CA, KRA, OCSP, TKS (Tomcat)

# Base instance directory paths
my $pki_instance_path      = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $acl_instance_path      = "";  # CA, KRA, OCSP, TKS
my $alias_instance_path    = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $bin_instance_path      = "";  # TPS
my $cgibin_instance_path   = "";  # TPS (Apache)
my $conf_instance_path     = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $docroot_instance_path  = "";  # RA, TPS (Apache)
my $emails_instance_path   = "";  # CA
my $lib_instance_path      = "";  # RA, TPS
my $logs_instance_path     = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $profiles_instance_path = "";  # CA, KRA, OCSP, TKS
my $scripts_instance_path  = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $shared_instance_path   = "";  # CA, KRA, OCSP, TKS (Tomcat)
my $temp_instance_path     = "";  # CA, KRA, OCSP, TKS (Tomcat)
my $webapps_instance_path  = "";  # CA, KRA, OCSP, TKS
my $webapps_subsystem_instance_path  = "";  # CA, KRA, OCSP, TKS
my $work_instance_path     = "";  # CA, KRA, OCSP, TKS (Tomcat)

# Base instance symbolic link paths
my $common_instance_symlink_path  = "";  # CA, KRA, OCSP, TKS
my $conf_instance_symlink_path    = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $logs_instance_symlink_path    = "";  # CA, KRA, OCSP, TKS, RA, TPS
my $run_instance_symlink_path     = "";  # RA, TPS

# Subdirectory paths
my $cgi_home_instance_file_path               = "";  # TPS
my $cgi_home_subsystem_file_path              = "";  # TPS
my $cgi_demo_instance_file_path               = "";  # TPS
my $cgi_demo_subsystem_file_path              = "";  # TPS
my $cgi_so_instance_file_path                 = "";  # TPS
my $cgi_so_subsystem_file_path                = "";  # TPS
my $cgi_so_instance_enroll_file_path          = "";  # TPS
my $cgi_so_subsystem_enroll_file_path         = "";  # TPS
my $cgi_sow_instance_file_path                = "";  # TPS
my $cgi_sow_subsystem_file_path               = "";  # TPS
my $cgi_sow_instance_cgi_file_path            = "";  # TPS
my $cgi_sow_subsystem_cgi_file_path           = "";  # TPS
my $cgi_sow_instance_cfg_pl_path              = "";  # TPS
my $addAgents_ldif_instance_file_path         = "";  # TPS
my $addAgents_ldif_subsystem_file_path        = "";  # TPS
my $addIndexes_ldif_instance_file_path        = "";  # TPS
my $addIndexes_ldif_subsystem_file_path       = "";  # TPS
my $addTokens_ldif_instance_file_path         = "";  # TPS
my $addTokens_ldif_subsystem_file_path        = "";  # TPS
my $addVLVIndexes_ldif_instance_file_path     = "";  # TPS
my $addVLVIndexes_ldif_subsystem_file_path    = "";  # TPS
my $apachectl_instance_file_path              = "";  # TPS
my $apachectl_subsystem_file_path             = "";  # TPS
my $catalina_sh_instance_file_path            = "";  # CA, KRA, OCSP, TKS
my $catalina_sh_subsystem_file_path           = "";  # CA, KRA, OCSP, TKS
my $certsrv_jar_file_path                     = "";  # CA, KRA, OCSP, TKS
my $certsrv_jar_symlink_path                  = "";  # CA, KRA, OCSP, TKS
my $cms_jar_file_path                         = "";  # CA, KRA, OCSP, TKS
my $cms_jar_symlink_path                      = "";  # CA, KRA, OCSP, TKS
my $nsutil_jar_file_path                      = "";  # CA, KRA, OCSP, TKS
my $nsutil_jar_symlink_path                   = "";  # CA, KRA, OCSP, TKS
my $cmsutil_jar_file_path                     = "";  # CA, KRA, OCSP, TKS
my $cmsutil_jar_symlink_path                  = "";  # CA, KRA, OCSP, TKS
my $cmsbundle_jar_file_path                   = "";  # CA, KRA, OCSP, TKS
my $cmsbundle_jar_symlink                     = "";  # CA, KRA, OCSP, TKS
my $cmscore_jar_file_path                     = "";  # CA, KRA, OCSP, TKS
my $cmscore_jar_symlink_path                  = "";  # CA, KRA, OCSP, TKS
my $httpd_conf_instance_file_path             = "";  # RA, TPS
my $httpd_conf_subsystem_file_path            = "";  # RA, TPS
my $index_html_instance_file_path             = "";  # CA, KRA, OCSP, TKS
my $index_html_subsystem_file_path            = "";  # CA, KRA, OCSP, TKS
my $java_pki_flavor_jar_path                  = "";  # CA, KRA, OCSP, TKS
my $magic_instance_file_path                  = "";  # RA, TPS
my $magic_subsystem_file_path                 = "";  # RA, TPS
my $mime_types_instance_file_path             = "";  # RA, TPS
my $mime_types_subsystem_file_path            = "";  # RA, TPS
my $noise_instance_file_path                  = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $nss_conf_instance_file_path               = "";  # RA, TPS
my $nss_conf_subsystem_file_path              = "";  # RA, TPS
my $perl_conf_instance_file_path              = "";  # RA, TPS
my $perl_conf_subsystem_file_path             = "";  # RA, TPS
my $osutil_jar_file_path                      = "";  # CA, KRA, OCSP, TKS
my $osutil_jar_symlink_path                   = "";  # CA, KRA, OCSP, TKS
my $password_conf_instance_file_path          = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $perl_instance_symlink_path                = "";  # RA, TPS
my $perl_subsystem_path                       = "";  # RA, TPS
my $pfile_instance_file_path                  = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $pwcache_conf_instance_file_path           = "";  # RA, TPS
my $pki_cfg_instance_file_path                = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $pki_cfg_subsystem_file_path               = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $schemaMods_ldif_instance_file_path        = "";  # RA, TPS
my $schemaMods_ldif_subsystem_file_path       = "";  # RA, TPS
my $server_xml_instance_file_path             = "";  # CA, KRA, OCSP, TKS
my $server_xml_subsystem_file_path            = "";  # CA, KRA, OCSP, TKS
my $servercertnick_conf_instance_file_path    = "";  # CA, KRA, OCSP, TKS
my $servercertnick_conf_subsystem_file_path   = "";  # CA, KRA, OCSP, TKS
my $subsystem_jar_file_path                   = "";  # CA, KRA, OCSP, TKS
my $subsystem_jar_symlink_path                = "";  # CA, KRA, OCSP, TKS
my $tomcat5_conf_subsystem_file_path          = "";  # CA, KRA, OCSP, TKS
my $tomcat5_conf_instance_file_path           = "";  # CA, KRA, OCSP, TKS
my $velocity_prop_instance_file_path          = "";  # CA, KRA, OCSP, TKS
my $velocity_prop_subsystem_file_path         = "";  # CA, KRA, OCSP, TKS
my $web_xml_instance_file_path                = "";  # CA, KRA, OCSP, TKS
my $web_xml_subsystem_file_path               = "";  # CA, KRA, OCSP, TKS
my $webapps_root_instance_path                = "";  # CA, KRA, OCSP, TKS
my $webapps_root_subsystem_path               = "";  # CA, KRA, OCSP, TKS
my $webapps_subsystem_instance_path           = "";  # CA, KRA, OCSP, TKS
my $webinf_instance_path                      = "";  # CA, KRA, OCSP, TKS
my $webinf_lib_instance_path                  = "";  # CA, KRA, OCSP, TKS
my $webinf_subsystem_path                     = "";  # CA, KRA, OCSP, TKS
my $profile_select_template_subsystem_file_path = ""; #CA
my $profile_select_template_instance_file_path = "";  #CA

# PKI init script variables
my $default_init_scripts_path                 = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS
my $pki_init_script                           = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS
my $pki_init_script_command                   = "";  # CA, KRA, OCSP, TKS,
                                                     # RA, TPS

# PKI registry variables
my $default_registry_path                     = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS
my $pki_registry_path                         = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS
my $pki_registry_subsystem_path               = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS
my $pki_instance_registry                     = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS
my $pki_instance_registry_entry               = "";  # CA, KRA, OCSP, TKS
                                                     # RA, TPS

# PKI creation variables
my $host = "";
my $db_password = 0;
my $random = 0;


##############################################################
# Platform-Dependent Data Initialization
##############################################################

if( $^O eq "linux" ) {
    $setup_base_subsystem_dir         = "setup";  # CA, KRA, OCSP, TKS, RA, TPS
    $setup_subsystem_path             = "";       # CA, KRA, OCSP, TKS, RA, TPS
    $setup_config_instance_file_path  = "";       # CA, KRA, OCSP, TKS, RA, TPS
    $setup_config_subsystem_file_path = "";       # CA, KRA, OCSP, TKS, RA, TPS

    # Linux required desktop files
    $setup_config_area = "/usr/share/applications";
    $setup_config_name = "config.desktop";

    # Linux init scripts
    $default_init_scripts_path = "/etc/rc.d/init.d";

    # Linux registry
    $default_registry_path = "/etc/sysconfig";

    # Platform-specific directories
    @pki_static_directories = ( "temp",
                                "shared",
                                "shared/lib",
                                "shared/common",
                                "shared/lib",
                                "work",
                                "setup" );

    # Superuser and group to give to PKI installed files
    $root_user = "root";
    $root_group = "root";
} elsif( $^O eq "solaris" ) {
    # Platform-specific directories
    @pki_static_directories = ( "temp",
                                "shared",
                                "shared/lib",
                                "shared/common",
                                "shared/lib",
                                "work" );

    # Solaris init scripts
    $default_init_scripts_path      = "/etc/init.d";

    # Solaris registry
    $default_registry_path = "/etc/inet";

    # Superuser and group to give to PKI installed files
    $root_user = "root";
    $root_group = "other";
} else {
    print( STDERR
           "ERROR:  Unsupported platform '$^O'!\n" );
    print( STDOUT "\n" );
    exit 255;
}


##############################################################
# Local Data Initialization
##############################################################

# Initialize Java-specific variables
if( $^O eq "linux" ) {
    if( $default_hardware_platform eq "i386" ) {
        # 32-bit Linux

        # Supported hardware token PKCS #11 modules
        %supported_sec_modules_hash = ( "lunasa",
                                        "/usr/lunasa/lib/libCryptoki2.so",
                                        "nfast",
                                        "/opt/nfast/toolkits/pkcs11/libcknfast.so"
                                      );
    } elsif( $default_hardware_platform eq "x86_64" ) {
        # 64-bit Linux

        # Supported hardware token PKCS #11 modules
        %supported_sec_modules_hash = ( "lunasa",
                                        "/usr/lunasa/lib/libCryptoki2.so",
                                        "nfast",
                                        "/opt/nfast/toolkits/pkcs11/libcknfast.so"
                                      );
    } else {
        print( STDERR
               "ERROR:  Unsupported '$^O' hardware platform "
             . "'$default_hardware_platform'!\n" );
        print( "\n" );
        exit 255;
    }
} elsif( $^O eq "solaris" ) {
    if( $default_hardware_platform eq "sparc" ) {
        # 32-bit Solaris

        # Supported hardware token PKCS #11 modules
        %supported_sec_modules_hash = ( "lunasa",
                                        "/usr/lunasa/lib/libCryptoki2.so",
                                        "nfast",
                                        "/opt/nfast/toolkits/pkcs11/libcknfast-32.so"
                                      );
    } elsif( $default_hardware_platform eq "sparcv9" ) {
        # 64-bit Solaris

        # Supported hardware token PKCS #11 modules
        %supported_sec_modules_hash = ( "lunasa",
                                        "/usr/lunasa/lib/libCryptoki2.so",
                                        "nfast",
                                        "/opt/nfast/toolkits/pkcs11/libcknfast-64.so"
                                      );
    } else {
        print( STDERR
               "ERROR:  Unsupported '$^O' hardware platform "
             . "'$default_hardware_platform'!\n" );
        print( "\n" );
        exit 255;
    }
} else {
    print( STDERR
           "ERROR:  Unsupported platform '$^O'!\n" );
    print( "\n" );
    exit 255;
}

# Links created via initial "tomcat" installation that MUST be removed!!!
if( -l $jdbc_stdext_link ) {
    my $rv = `rm -f $jdbc_stdext_link`;
    if( $rv ) {
        print( STDERR
               "ERROR:  Unable to remove symbolic link called "
             . "$jdbc_stdext_link!\n" );
        print( "\n" );
        exit 255;
    }
}

if( -l $jndi_link ) {
    my $rv = `rm -f $jndi_link`;
    if( $rv ) {
        print( STDERR
               "ERROR:  Unable to remove symbolic link called "
             . "$jndi_link!\n" );
        print( "\n" );
        exit 255;
    }
}

if( -l $jaas_link ) {
    my $rv = `rm -f $jaas_link`;
    if( $rv ) {
        print( STDERR
               "ERROR:  Unable to remove symbolic link called "
             . "$jaas_link!\n" );
        print( "\n" );
        exit 255;
    }
}

# Establish PKI-level registry
$pki_registry_path = $default_registry_path
                   . "/" . $pki_flavor;


##############################################################
# PKI Instance Creation Subroutines
##############################################################

# no args
# no return value
sub usage()
{
    print( STDOUT "\n" );
    print( STDOUT
           "###############################################################################\n"
         . "###   USAGE:  CA, KRA, OCSP, or TKS subsystem instance creation (Tomcat)    ###\n"
         . "###############################################################################\n\n"
         . "pkicreate -pki_instance_root=<pki_instance_root>   "
         . "# Instance root directory\n"
         . "                                                   "
         . "# destination\n\n"
         . "          -pki_instance_name=<pki_instance_id>     "
         . "# Unique PKI subsystem\n"
         . "                                                   "
         . "# instance name\n\n"
         . "          -subsystem_type=<subsystem_type>         "
         . "# Subsystem type\n"
         . "                                                   "
         . "# [ca | kra | ocsp | tks]\n\n"
         . "          #####################################################################\n"
         . "          ###   SELECT separate secure ports for AGENT, EE, and ADMIN:      ###\n"
         . "          #####################################################################\n\n"
         . "          -agent_secure_port=<agent_secure_port>   "
         . "# Agent secure port\n\n"
         . "          -ee_secure_port=<ee_secure_port>         "
         . "# EE secure port\n\n"
         . "          -admin_secure_port=<admin_secure_port>   " 
         . "# Admin secure port\n\n"
         . "          #####################################################################\n"
         . "          ###   ... and a client auth EE port, required for CAs only        ###\n"
         . "          #####################################################################\n\n"
         . "          -ee_secure_client_auth_port=<ee_secure_client_auth_port>\n"
         . "                                         # EE secure client authentication port\n\n"
         . "          #####################################################################\n"
         . "          ###   OR SELECT a single secure port shared by AGENT,EE and ADMIN ###\n"
         . "          #####################################################################\n\n"
         . "          -secure_port=<secure_port>               "
         . "# Secure port\n"
         . "                                                   "
         . "# (shared by Agent,\n"
         . "                                                   "
         . "#  EE, and Admin)\n\n"
         . "          #####################################################################\n"
         . "          ###   END secure port SELECTION                                   ###\n"
         . "          #####################################################################\n\n"
         . "          -unsecure_port=<unsecure_port>           "
         . "# Unsecure port\n\n"
         . "          -tomcat_server_port=<tomcat_server_port> "
         . "# Unique port for each\n"
         . "                                                   "
         . "# Tomcat instance\n\n"
         . "          [-user=<username>]                       "
         . "# User ownership\n"
         . "                                                   "
         . "# (must ALSO specify\n"
         . "                                                   "
         . "#  group ownership)\n"
         . "                                                   "
         . "#\n"
         . "                                                   "
         . "# [Default=pkiuser]\n\n"
         . "          [-group=<groupname>]                     "
         . "# Group ownership\n"
         . "                                                   "
         . "# (must ALSO specify\n"
         . "                                                   "
         . "#  user ownership)\n"
         . "                                                   "
         . "#\n"
         . "                                                   "
         . "# [Default=pkiuser]\n\n"
         . "          [-redirect conf=<real conf dir path>]    "
         . "# Redirection of\n"
         . "                                                   "
         . "# 'conf' directory\n\n"
         . "          [-redirect logs=<real logs dir path>]    "
         . "# Redirection of\n"
         . "                                                   "
         . "# 'logs' directory\n\n"
         . "          [-verbose]                               "
         . "# Print out liberal info\n"
         . "                                                   "
         . "# during 'pkicreate'\n\n"
         . "          [-help]                                  "
         . "# Print out this screen\n\n\n"
         . "###############################################################################\n"
         . "###   USAGE:  RA or TPS subsystem instance creation (Apache)                ###\n"
         . "###############################################################################\n\n"
         . "pkicreate -pki_instance_root=<pki_instance_root>   "
         . "# Instance root directory\n"
         . "                                                   "
         . "# destination\n\n"
         . "          -pki_instance_name=<pki_instance_id>     "
         . "# Unique PKI subsystem\n"
         . "                                                   "
         . "# instance name\n\n"
         . "          -subsystem_type=<subsystem_type>         "
         . "# Subsystem type\n"
         . "                                                   "
         . "# [ra | tps]\n\n"
         . "          -secure_port=<secure_port>               "
         . "# Secure port\n"
         . "                                                   "
         . "# (clientauth)\n"
         . "                                                   "
         . "# for each\n"
         . "                                                   "
         . "# Apache instance\n\n"
         . "          -non_clientauth_secure_port=<non_clientauth_secure_port>\n\n"
         . "                                                   "
         . "# Secure port\n"
         . "                                                   "
         . "# (non-clientauth)\n"
         . "                                                   "
         . "# for each\n"
         . "                                                   "
         . "# Apache instance\n\n"
         . "          -unsecure_port=<unsecure_port>           "
         . "# Unsecure port\n\n"
         . "          [-user=<username>]                       "
         . "# User ownership\n"
         . "                                                   "
         . "# (must ALSO specify\n"
         . "                                                   "
         . "#  group ownership)\n"
         . "                                                   "
         . "#\n"
         . "                                                   "
         . "# [Default=pkiuser]\n\n"
         . "          [-group=<groupname>]                     "
         . "# Group ownership\n"
         . "                                                   "
         . "# (must ALSO specify\n"
         . "                                                   "
         . "#  user ownership)\n"
         . "                                                   "
         . "#\n"
         . "                                                   "
         . "# [Default=pkiuser]\n\n"
         . "          [-redirect conf=<real conf dir path>]    "
         . "# Redirection of\n"
         . "                                                   "
         . "# 'conf' directory\n\n"
         . "          [-redirect logs=<real logs dir path>]    "
         . "# Redirection of\n"
         . "                                                   "
         . "# 'logs' directory\n\n"
         . "          [-verbose]                               "
         . "# Print out liberal info\n"
         . "                                                   "
         . "# during 'pkicreate'\n\n"
         . "          [-help]                                  "
         . "# Print out this screen\n\n\n" );

    print( STDOUT
           "###############################################################################\n"
         . "###   EXAMPLES:                                                             ###\n"
         . "###       PKI (Tomcat) subsystem instance creation of a  CA                 ###\n"
         . "###       PKI (Tomcat) subsystem instance creation of a  Subordinate CA     ###\n"
         . "###       PKI (Tomcat) subsystem instance creation of a  KRA                ###\n"
         . "###       PKI (Tomcat) subsystem instance creation of an OCSP               ###\n"
         . "###       PKI (Tomcat) subsystem instance creation of a  TKS                ###\n"
         . "###       PKI (Apache) subsystem instance creation of an RA                 ###\n"
         . "###       PKI (Apache) subsystem instance creation of a  TPS                ###\n"
         . "###       PKI (Apache) subsystem instance creation of a  second TPS         ###\n"
         . "###############################################################################\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-ca          \\\n"
         . "          -subsystem_type=ca                 \\\n"
         . "          -agent_secure_port=9443            \\\n"
         . "          -ee_secure_port=9444               \\\n"
         . "          -ee_secure_client_auth_port=9446   \\\n"
         . "          -admin_secure_port=9445            \\\n"
         . "          -unsecure_port=9180                \\\n"
         . "          -tomcat_server_port=9701           \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-ca         \\\n"
         . "          -redirect logs=/var/log/pki-ca     \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-subca       \\\n"
         . "          -subsystem_type=ca                 \\\n"
         . "          -agent_secure_port=9543            \\\n"
         . "          -ee_secure_port=9544               \\\n"
         . "          -ee_secure_client_auth_port=9546   \\\n"
         . "          -admin_secure_port=9545            \\\n"
         . "          -unsecure_port=9580                \\\n"
         . "          -tomcat_server_port=9801           \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-subca      \\\n"
         . "          -redirect logs=/var/log/pki-subca  \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-kra         \\\n"
         . "          -subsystem_type=kra                \\\n"
         . "          -agent_secure_port=10443           \\\n"
         . "          -ee_secure_port=10444              \\\n"
         . "          -admin_secure_port=10445           \\\n"
         . "          -unsecure_port=10180               \\\n"
         . "          -tomcat_server_port=10701          \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-kra        \\\n"
         . "          -redirect logs=/var/log/pki-kra    \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-ocsp        \\\n"
         . "          -subsystem_type=ocsp               \\\n"
         . "          -agent_secure_port=11443           \\\n"
         . "          -ee_secure_port=11444              \\\n"
         . "          -admin_secure_port=11445           \\\n"
         . "          -unsecure_port=11180               \\\n"
         . "          -tomcat_server_port=11701          \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-ocsp       \\\n"
         . "          -redirect logs=/var/log/pki-ocsp   \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-tks         \\\n"
         . "          -subsystem_type=tks                \\\n"
         . "          -agent_secure_port=13443           \\\n"
         . "          -ee_secure_port=13444              \\\n"
         . "          -admin_secure_port=13445           \\\n"
         . "          -unsecure_port=13180               \\\n"
         . "          -tomcat_server_port=13701          \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-tks        \\\n"
         . "          -redirect logs=/var/log/pki-tks    \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-ra          \\\n"
         . "          -subsystem_type=ra                 \\\n"
         . "          -secure_port=12889                 \\\n"
         . "          -non_clientauth_secure_port=12890  \\\n"
         . "          -unsecure_port=12888               \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-ra         \\\n"
         . "          -redirect logs=/var/log/pki-ra     \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-tps         \\\n"
         . "          -subsystem_type=tps                \\\n"
         . "          -secure_port=7889                  \\\n"
         . "          -non_clientauth_secure_port=7890   \\\n"
         . "          -unsecure_port=7888                \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-tps        \\\n"
         . "          -redirect logs=/var/log/pki-tps    \\\n"
         . "          -verbose\n\n"
         . "pkicreate -pki_instance_root=/var/lib        \\\n"
         . "          -pki_instance_name=pki-tps1        \\\n"
         . "          -subsystem_type=tps                \\\n"
         . "          -secure_port=7989                  \\\n"
         . "          -non_clientauth_secure_port=7990   \\\n"
         . "          -unsecure_port=7988                \\\n"
         . "          -user=pkiuser                      \\\n"
         . "          -group=pkiuser                     \\\n"
         . "          -redirect conf=/etc/pki-tps1       \\\n"
         . "          -redirect logs=/var/log/pki-tps1   \\\n"
         . "          -verbose\n\n" );

    print( STDOUT
           "IMPORTANT:  Must be run as root!\n\n" );

    return;
}


# arg0 instance name
# return 1 - exists, or
# return 0 - DOES NOT exist
sub pki_instance_already_exists
{
    my $name = $_[0];
    my $result = 0;
    my $instance = "";

    $instance = $pki_registry_path
              . "/" . $subsystem_type
              . "/" . $name;

    if( -e $instance ) {
        $result = 1;
    }

    return $result;
}


# no args
# return 1 - success, or
# return 0 - failure
sub parse_arguments()
{
    my $l_secure_port        = -1;
    my $l_non_clientauth_secure_port = -1;
    my $l_unsecure_port      = -1;
    my $l_tomcat_server_port = -1;
    my $l_agent_secure_port  = -1;
    my $l_ee_secure_port     = -1;
    my $l_ee_secure_client_auth_port     = -1;
    my $l_admin_secure_port  = -1;
    my $show_help            = 0;

    $result = GetOptions( "help" => \$show_help,
                          "pki_instance_root=s" => \$pki_instance_root,
                          "pki_instance_name=s" => \$pki_instance_name,
                          "subsystem_type=s" => \$subsystem_type,
                          "secure_port:i" => \$l_secure_port,
                          "non_clientauth_secure_port:i" => \$l_non_clientauth_secure_port,
                          "unsecure_port:i" => \$l_unsecure_port,
                          "agent_secure_port:i" => \$l_agent_secure_port,
                          "ee_secure_port:i" => \$l_ee_secure_port,
                          "ee_secure_client_auth_port:i" => \$l_ee_secure_client_auth_port,
                          "admin_secure_port:i" => \$l_admin_secure_port, 
                          "tomcat_server_port:i" => \$l_tomcat_server_port,
                          "user=s" => \$username,
                          "group=s" => \$groupname,
                          "verbose" => \$verbose,
                          "redirect=s" => \%redirects );


    ## Optional "-help" option - no "mandatory" options are required
    if( $show_help ) {
        usage();
        return 0;
    }


    ## Mandatory "-pki_instance_root=s" option
    if( $pki_instance_root eq "" ) {
        usage();
        emit( "Must have value for -pki_instance_root!\n", "error" );
        return 0;
    }

    if( $pki_instance_root eq "/" ) {
        usage();
        emit( "Don't even think about making root the pki_instance_root! "
            . "Try again.\n", "error" );
        return 0;
    }

    # Remove all trailing directory separators ('/')
    $pki_instance_root =~ s/\/+$//;

    if( !is_path_valid( $pki_instance_root ) ) {
        usage();
        emit( "Target directory $pki_instance_root is not a "
            . "legal directory try again.\n",
              "error" );
        return 0;
    }

    ## Mandatory "-subsystem_type=s" option
    if( $subsystem_type ne $CA   &&
        $subsystem_type ne $KRA  &&
        $subsystem_type ne $OCSP &&
        $subsystem_type ne $TKS  &&
        $subsystem_type ne $RA   &&
        $subsystem_type ne $TPS ) {
        usage();
        emit( "Illegal  value => $subsystem_type :  for -subsystem_type!\n",
              "error" );
        return 0;
    }

    $pki_subsystem_path = $pki_subsystem_common_area
                        . "/" . $subsystem_type;

    if( !( -d "$pki_subsystem_path" ) ) {
        usage();
        emit( "$pki_subsystem_path not present.  "
            . "Please install the corresponding subsystem RPM first!\n",
              "error" );
        return 0;
    } else {
        emit( "    subsystem_type      $subsystem_type\n" );
    }


    ## Mandatory "-pki_instance_name=s" option
    if( $pki_instance_name eq "" ) {
        usage();
        emit( "Must have value for -pki_instance_name!\n", "error" );
        return 0;
    }

    if( !is_name_valid( $pki_instance_name ) ) {
        usage();
        emit( "Illegal Value => $pki_instance_name for -pki_instance_name!\n",
              "error" );
        return 0;
    }

    if( pki_instance_already_exists( $pki_instance_name ) ) {
        usage();
        emit( "An instance named $pki_instance_name "
            . "already exists; please try again.\n", "error" );
        return 0;
    }

    $pki_instance_path  = $pki_instance_root
                        . "/" . $pki_instance_name;

    if( directory_exists( $pki_instance_path ) ) {
        usage();
        emit( "Target directory $pki_instance_path "
            . "already exists; clean up and "
            . "try again.\n", "error" );
        return 0;
    }

    # capture installation information in a log file
    # (always overwrite this file)
    $logfile = "/var/log/$pki_instance_name-install.log";
    open_logfile( $logfile );
    chmod( $default_file_permissions, $logfile );
    push( @installed_files, $logfile );

    emit( "Capturing installation information in $logfile.\n" );

    emit( "Parsing PKI creation arguments ...\n" );

    if( $verbose ) {
        emit( "    verbose mode is ENABLED\n" );
    }

    emit( "    pki_instance_root   $pki_instance_root\n" );
    emit( "    pki_instance_name   $pki_instance_name\n" );

    ## Mandatory "-secure_port=<secure_port>" option
    if( $l_secure_port >= 0 ) {
        $secure_port = $l_secure_port;

        emit( "    secure_port         $secure_port\n" );
    } else {
        if( $l_agent_secure_port == -1)
        {
            usage();
            emit( "Must include value for secure_port!\n", "error" );
            return 0;
        }
    }

    ## Mandatory "-non_clientauth_secure_port=<non_clientauth_secure_port>"
    ## option/exclusion
    if( ( $subsystem_type eq $RA || $subsystem_type eq $TPS ) ) {
        if( $l_non_clientauth_secure_port >= 0 ) {
            $non_clientauth_secure_port = $l_non_clientauth_secure_port;

            emit( "    non_clientauth_secure_port         "
                . "$non_clientauth_secure_port\n" );
        } else {
            if( $l_non_clientauth_secure_port == -1)
            {
                usage();
                emit( "Must include value for non_clientauth_secure_port!\n",
                      "error" );
                return 0;
            }
        }

        if( $l_agent_secure_port > 0 ||
            $l_ee_secure_port > 0    ||
            $l_ee_secure_client_auth_port > 0    ||
            $l_admin_secure_port > 0)  {
            usage();
            emit( "Must NOT include values for any agent|admin|ee ports!\n",
                  "error");
            return 0;
        }
    } else {
        ## Mandatory EXCLUSION for CA, KRA, OCSP, and TKS subsystems
        if( $l_non_clientauth_secure_port != -1 ) {
            usage();
            emit( "Must NOT include value for non_clientauth_secure_port!\n",
                  "error" );
            return 0;
        }
    }
 
    ## Mandatory "-unsecure_port=<unsecure_port>" option
    if( $l_unsecure_port >= 0 ) {
        $unsecure_port = $l_unsecure_port;

        emit( "    unsecure_port       $unsecure_port\n" );
    } else {
        usage();
        emit( "Must include value for unsecure_port!\n", "error" );
        return 0;
    }

    ## Mandatory "-tomcat_server_port=<tomcat_server_port>" option/exclusion
    if( !($subsystem_type eq $RA || $subsystem_type eq $TPS ) ) {
        ## Mandatory OPTION for CA, KRA, OCSP, and TKS subsystems
        if( $l_tomcat_server_port < 0 ) {
            usage();
            emit( "Must include value for tomcat_server_port!\n", "error" );
            return 0;
        }

        $tomcat_server_port = $l_tomcat_server_port;

        emit( "    tomcat_server_port  $tomcat_server_port\n" );
    } else {
        ## Mandatory EXCLUSION for RA and TPS subsystems
        if( $l_tomcat_server_port != -1 ) {
            usage();
            emit( "Must NOT include value for tomcat_server_port!\n",
                  "error" );
            return 0;
        }
    }

    if( $l_agent_secure_port >= 0 ) {
        $agent_secure_port = $l_agent_secure_port;
     
        emit( "    agent_secure_port   $agent_secure_port\n");

    }

    ## Mandatory ee_secure_port  if "-agent_secure_port" is given 

    if( $l_ee_secure_port >= 0 ) {
        $ee_secure_port = $l_ee_secure_port;
     
        emit( "    ee_secure_port      $ee_secure_port\n");

    } else {
        if($agent_secure_port >= 0) {
            emit( "Must include value for ee_secure_port if agent_secure_port is given!\n");
        }
    }

    ## Mandatory ee_secure_client_auth_port  if "-agent_secure_port" is given, and CA subsystem

    if( $l_ee_secure_client_auth_port >= 0 ) {
        $ee_secure_client_auth_port = $l_ee_secure_client_auth_port;
     
        emit( "    ee_secure_client_auth_port      $ee_secure_client_auth_port\n");

    } else {
        if (($agent_secure_port >= 0) && ($subsystem_type eq $CA)) {
            usage();
            emit( "For CAs, must include value for ee_secure_client_auth_port if agent_secure_port is given!\n");
            return 0;
        }
    }

     ## Mandatory admin_secure_port if "-agent_secure_port" is given 

    if( $l_admin_secure_port >= 0 ) {
        $admin_secure_port = $l_admin_secure_port;
    
        emit( "    admin_secure_port   $admin_secure_port\n");

    } else {
        if($agent_secure_port >= 0) {
            emit( "Must include value for admin_secure_port if agent_secure_port is given!\n");
        }
    }

    if (!AreConnectorPortsValid($secure_port,$unsecure_port,$agent_secure_port,
         $ee_secure_port,$ee_secure_client_auth_port, $admin_secure_port ) )
    {
        usage();
        emit( "Invalid port numbers submitted!\n","error" );
        return 0;
    }


    ## Optional "-group=<groupname>" option
    if( $groupname ne "" ) {
        if( $username eq "" ) {
            usage();
            emit( "Must ALSO specify user ownership using -user!\n",
                  "error" );
            return 0;
        }

        if( !group_exists( $groupname ) ) {
            if( !create_group( $groupname ) ) {
                usage();
                emit( "Unable to create group '$groupname' on this machine!\n",
                      "error" );
                return 0;
            }
        }

        # Overwrite default value of $pki_group with user-specified $groupname
        $pki_group = $groupname;
    }


    # At this point in time, ALWAYS check that "$pki_group" exists!
    if( !group_exists( $pki_group ) ) {
        if( !create_group( $pki_group ) ) {
            usage();
            emit( "Unable to create group '$pki_group' on this machine!\n",
                  "error" );
            return 0;
        }
    }


    ## Optional "-user=<username>" option
    if( $username ne "" ) {
        if( $groupname eq "" ) {
            usage();
            emit( "Must ALSO specify group ownership using -group!\n",
                  "error" );
            return 0;
        }

        if( !user_exists( $username ) ) {
            if( !create_user( $username, $groupname ) ) {
                usage();
                emit( "Unable to create user '$username' on this machine!\n",
                      "error" );
                return 0;
            }
        }

        # Overwrite default value of $pki_user with user-specified $username
        $pki_user = $username;
    }


    # At this point in time, ALWAYS check that "$pki_user" exists!
    if( !user_exists( $pki_user ) ) {
        if( !create_user( $pki_user, $pki_group ) ) {
            usage();
            emit( "Unable to create user '$pki_user' on this machine!\n",
                  "error" );
            return 0;
        }
    }


    # At this point in time, ALWAYS check that shell access for "$pki_user" is
    # disallowed; for now, simply notify the user performing the installation
    # and continue
    if( !user_disallows_shell( $pki_user ) ) {
        emit( "Please contact your system administrator "
            . "to disallow shell access for '$pki_user'!\n" );
    }


    # At this point in time, ALWAYS check that "$pki_user"
    # is a valid member of "$pki_group"
    #
    # NOTE:  Uncomment the following code to enforce a strict policy of
    #        requiring $pki_user to be a member of $pki_group . . .
    #
    # if( !user_is_a_member_of_group( $pki_user, $pki_group ) ) {
    #     usage();
    #     emit( "The user '$pki_user' is NOT a member of group '$pki_group'!\n",
    #           "error" );
    #     return 0;
    # }


    ## Optional "-redirect <dir_name>=<real dir path> ..." option
    while( my ($key, $value) = each( %redirects ) ) {
        if( !is_path_valid( $value ) ) {
            usage();
            emit( "Illegal redirect directory value:  key=$key  value="
                . "$value\n", "error" );
            return 0;
        }

        if( $key eq "conf" ) {
            $redirected_conf_path = $value;
            emit( "setting conf_path $redirected_conf_path\n" );
        } elsif( $key eq "logs" ) {
            $redirected_logs_path = $value;
            emit( "setting logs_path $redirected_logs_path\n" );
        } else {
            usage();
            emit( "Illegal redirect directory key:  key=$key  value="
                . "$value\n", "error" );
            return 0;
        }

        emit( "redirect            $key => $value\n" );
    }

    ## selinux warning
    if (($pki_instance_root ne "/var/lib") && ($^O eq "linux")) {
        print STDOUT 
            "WARNING: This utility will attempt to relabel the selinux context of the directory\n" . 
            $pki_instance_path . " and the files within it as pki_$subsystem_type" . "_var_lib_t . \n" .
            "Depending on the location of pki_instance_root and the selinux rules currently\n" .
            "in place on the system, this may not succeed.  In that case, the directory may\n" .
            "have to be manually relabeled, or selinux will have to be run in permissive mode.\n\n" .
            "It is therefore recommended that the default setting of /var/lib be used for pki_instance_root.\n\n";
ASK_CONTINUE_NONSTD_INSTANCE_ROOT:
        $confirm  = prompt( "You have chosen the following value for pki_instance_root instead: " .  $pki_instance_root .
                            "\nDo you wish to proceed with this value (Y/N)?" );

        if( $confirm eq "N" || $confirm eq "n" ) {
            return 0;
        } elsif( $confirm ne "Y" && $confirm ne "y" ) {
           goto ASK_CONTINUE_NONSTD_INSTANCE_ROOT;
        }
    }  

    return 1;
}


# no args
# no return value
sub initialize_subsystem_paths()
{
    ## Initialize subsystem directory paths (subsystem independent)
    $alias_subsystem_path    = $pki_subsystem_path
                             . "/" . $alias_base_subsystem_dir;
    $conf_subsystem_path     = $pki_subsystem_path
                             . "/" . $conf_base_subsystem_dir;
    $etc_subsystem_path      = $pki_subsystem_path
                             . "/" . $etc_base_subsystem_dir;
    $logs_subsystem_path     = $pki_subsystem_path
                             . "/" . $logs_base_subsystem_dir;
    if( $^O eq "linux" ) {
        $setup_subsystem_path = $pki_subsystem_path
                              . "/" . $setup_base_subsystem_dir;
    }

    ## Initialize subsystem directory paths (CA subsystems)
    if( $subsystem_type eq $CA ) {
        $emails_subsystem_path = $pki_subsystem_path
                               . "/" . $emails_base_subsystem_dir;
    }


    $common_ui_subsystem_path  = $pki_subsystem_common_area . "/" .
                                 "common-ui";
    $ui_subsystem_path         = $pki_subsystem_path . "-ui";

    ## Initialize subsystem directory paths (RA, TPS subsystems)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
        if( $subsystem_type eq $TPS ) {
            $applets_subsystem_path = $pki_subsystem_path
                                    . "/" . $applets_base_subsystem_dir;
            $bin_subsystem_path     = $default_system_user_libraries
                                    . "/" . $pki_flavor
                                    . "/" . $subsystem_type;
            $samples_subsystem_path = $pki_subsystem_path
                                    . "/" . $samples_base_subsystem_dir;
        }

        $lib_subsystem_path     = $pki_subsystem_path
                                . "/" . $lib_base_subsystem_dir;
        $scripts_subsystem_path = $pki_subsystem_path
                                . "/" . $scripts_base_subsystem_dir;

        # Apache Specific
        if( $subsystem_type eq $TPS ) {
            $cgibin_subsystem_path  = $pki_subsystem_path
                                    . "/" . $cgibin_base_subsystem_dir;
        }

        # Apache Specific
        $docroot_subsystem_path = $pki_subsystem_path
                                . "/" . $docroot_base_subsystem_dir;
    } else {

    ## Initialize subsystem directory paths (CA, KRA, OCSP, TKS subsystems)

        $acl_subsystem_path      = $pki_subsystem_path
                                 . "/" . $acl_base_subsystem_dir;
        $profiles_subsystem_path = $pki_subsystem_path
                                 . "/" . $profiles_base_subsystem_dir;
        $webapps_subsystem_path  = $pki_subsystem_path
                                 . "/" . $webapps_base_subsystem_dir;

        # Tomcat Specific
        $shared_subsystem_path   = $pki_subsystem_path
                                 . "/" . $shared_base_subsystem_dir;
        $temp_subsystem_path     = $pki_subsystem_path
                                 . "/" . $temp_base_subsystem_dir;
        $work_subsystem_path     = $pki_subsystem_path
                                 . "/" . $work_base_subsystem_dir;
    }

    return;
}


# no args
# no return value
sub initialize_instance_paths()
{
    ## Initialize instance directory paths (instance independent)
    $alias_instance_path = $pki_instance_path
                         . "/" . $alias_base_instance_dir;
    $conf_instance_path  = $pki_instance_path
                         . "/" . $conf_base_instance_dir;
    $logs_instance_path  = $pki_instance_path
                         . "/" . $logs_base_instance_dir;


    ## Initialize instance directory paths (CA instances)
    if( $subsystem_type eq $CA ) {
        $emails_instance_path = $pki_instance_path
                              . "/" . $emails_base_instance_dir;
    }


    ## Initialize instance directory paths (RA, TPS instances)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
        if( $subsystem_type eq $TPS ) {
            $bin_instance_path      = $pki_instance_path
                                    . "/" . $bin_base_instance_dir;
        }

        $lib_instance_path      = $pki_instance_path
                                . "/" . $lib_base_instance_dir;
        $scripts_instance_path  = $pki_instance_path
                                . "/" . $scripts_base_instance_dir;

        # Apache Specific
        if( $subsystem_type eq $TPS ) {
            $cgibin_instance_path   = $pki_instance_path
                                    . "/" . $cgibin_base_instance_dir;
        }

        # Apache Specific
        $docroot_instance_path  = $pki_instance_path
                                . "/" . $docroot_base_instance_dir;
    } else {
        ## Initialize instance directory paths (CA, KRA, OCSP, TKS instances)
        $acl_instance_path      = $pki_instance_path
                                . "/" . $acl_base_instance_dir;
        $profiles_instance_path = $pki_instance_path
                                . "/" . $profiles_base_instance_dir;
        $webapps_instance_path = $pki_instance_path
                                . "/" . $webapps_base_instance_dir;
        $webapps_subsystem_instance_path = $webapps_instance_path . "/" 
                                .  $subsystem_type;

        # Tomcat Specific
        $shared_instance_path = $pki_instance_path
                              . "/" . $shared_base_instance_dir;
        $temp_instance_path   = $pki_instance_path
                              . "/" . $temp_base_instance_dir;
        $work_instance_path   = $pki_instance_path
                              . "/" . $work_base_instance_dir;
    }

    return;
}


# no args
# no return value
sub initialize_instance_symlink_paths()
{
    ## Initialize instance symlinks (instance independent)
    $conf_instance_symlink_path = $pki_instance_path
                                . "/" . $conf_base_instance_symlink;
    $logs_instance_symlink_path = $pki_instance_path
                                . "/" . $logs_base_instance_symlink;


    ## Initialize instance symlinks (CA instances)
    # if( $subsystem_type eq $CA ) {
    # }


    ## Initialize instance symlinks (RA, TPS instances)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
        # Apache Specific
        $run_instance_symlink_path     = $pki_instance_path
                                       . "/" . $run_base_instance_symlink;
    } else {
       ## Initialize instance symlinks (CA, KRA, OCSP, TKS instances)
        $common_instance_symlink_path = $pki_instance_path
                                      . "/" . $common_base_instance_symlink;
    }

    return;
}


# no args
# no return value
sub initialize_subdirectory_paths()
{
    ## Initialize subdirectory paths (subsystem independent)
    $pki_cfg_subsystem_file_path               = $conf_subsystem_path
                                               . "/" . $pki_cfg_base_name;
    if( $^O eq "linux" ) {
        $setup_config_instance_file_path  = $setup_config_area
                                          . "/" . $pki_instance_name
                                          . "-" . $setup_config_name;
        $setup_config_subsystem_file_path = $setup_subsystem_path
                                          . "/" . $setup_config_name;
    }

    if( $subsystem_type eq $CA ) {
        $pki_init_script = $CA_INIT_SCRIPT;
    } elsif( $subsystem_type eq $KRA ) {
        $pki_init_script = $KRA_INIT_SCRIPT;
    } elsif( $subsystem_type eq $OCSP ) {
        $pki_init_script = $OCSP_INIT_SCRIPT;
    } elsif( $subsystem_type eq $RA ) {
        $pki_init_script = $RA_INIT_SCRIPT;
    } elsif( $subsystem_type eq $TKS ) {
        $pki_init_script = $TKS_INIT_SCRIPT;
    } elsif( $subsystem_type eq $TPS ) {
        $pki_init_script = $TPS_INIT_SCRIPT;
    }

    ## Initialize subdirectory paths (CA subsystems)
    if( $subsystem_type eq $CA ) {
        $profile_select_template_subsystem_file_path = $ui_subsystem_path 
                                                     . "/" . $webapps_base_subsystem_dir
                                                     . "/" . $subsystem_type
                                                     . "/ee/" . $subsystem_type
                                                     . "/" . $profile_select_base_name; 
        $profile_select_template_instance_file_path = $webapps_subsystem_instance_path
                                                     . "/ee/". $subsystem_type 
                                                     . "/" . $profile_select_base_name;
    }

    ## Initialize subdirectory paths (RA, TPS subsystems)
    if( $subsystem_type eq $RA  || $subsystem_type eq $TPS ) {

        if( $subsystem_type eq $TPS ) {

            $apachectl_instance_file_path          = $bin_instance_path
                                                   . "/" . $apachectl_base_name;
            $apachectl_subsystem_file_path         = $bin_subsystem_path
                                                   . "/" . $apachectl_base_name;
            $cgi_home_instance_file_path           = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_home_base_name;
            $cgi_home_subsystem_file_path          = $cgibin_subsystem_path
                                                   . "/"
                                                   . $cgi_home_base_name;
            $cgi_demo_instance_file_path           = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_demo_base_name;
            $cgi_demo_subsystem_file_path          = $cgibin_subsystem_path
                                                   . "/"
                                                   . $cgi_demo_base_name;
            $cgi_so_instance_file_path             = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_so_base_name;
            $cgi_so_subsystem_file_path            = $cgibin_subsystem_path
                                                   . "/"
                                                   . $cgi_so_base_name;
            $cgi_so_instance_enroll_file_path      = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_so_enroll_name;
            $cgi_so_subsystem_enroll_file_path     = $cgibin_subsystem_path
                                                   . "/"
                                                   . $cgi_so_enroll_name;
            $cgi_sow_instance_file_path            = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_sow_dir_name;
            $cgi_sow_subsystem_file_path           = $cgibin_subsystem_path
                                                   . "/"
                                                   . $cgi_sow_dir_name;
            $cgi_sow_instance_cfg_pl_path          = $cgibin_instance_path
                                                   . "/"
                                                   . $cgi_sow_cfg_pl_name;
            $addAgents_ldif_instance_file_path     = $scripts_instance_path
                                                   . "/"
                                                   . $addAgents_ldif_base_name;
            $addAgents_ldif_subsystem_file_path    = $scripts_subsystem_path
                                                   . "/"
                                                   . $addAgents_ldif_base_name;
            $addIndexes_ldif_instance_file_path    = $scripts_instance_path
                                                   . "/"
                                                   . $addIndexes_ldif_base_name;
            $addIndexes_ldif_subsystem_file_path   = $scripts_subsystem_path
                                                   . "/"
                                                   . $addIndexes_ldif_base_name;
            $addTokens_ldif_instance_file_path     = $scripts_instance_path
                                                   . "/"
                                                   . $addTokens_ldif_base_name;
            $addTokens_ldif_subsystem_file_path    = $scripts_subsystem_path
                                                   . "/"
                                                   . $addTokens_ldif_base_name;
            $addVLVIndexes_ldif_instance_file_path = $scripts_instance_path
                                                . "/"
                                                . $addVLVIndexes_ldif_base_name;
            $addVLVIndexes_ldif_subsystem_file_path = $scripts_subsystem_path
                                                . "/"
                                                . $addVLVIndexes_ldif_base_name;
            $schemaMods_ldif_instance_file_path    = $scripts_instance_path
                                                   . "/"
                                                   . $schemaMods_ldif_base_name;
            $schemaMods_ldif_subsystem_file_path   = $scripts_subsystem_path
                                                   . "/"
                                                   . $schemaMods_ldif_base_name;
        }

        $nss_pcache_instance_file_path          = $scripts_instance_path
                                                . "/"
                                                . $nss_pcache_base_name;
        $nss_pcache_subsystem_file_path         = $scripts_subsystem_path
                                                . "/"
                                                . $nss_pcache_base_name;
        $httpd_conf_subsystem_file_path         = $conf_subsystem_path
                                                . "/" . $httpd_conf_base_name;
        $magic_subsystem_file_path              = $conf_subsystem_path
                                                . "/" . $magic_base_name;
        $mime_types_subsystem_file_path         = $conf_subsystem_path
                                                . "/" . $mime_types_base_name;
        $nss_conf_subsystem_file_path           = $conf_subsystem_path
                                                . "/" . $nss_conf_base_name;
        $perl_conf_subsystem_file_path          = $conf_subsystem_path
                                                . "/" . $perl_conf_base_name;
        $perl_instance_symlink_path             = $lib_instance_path
                                                . "/"
                                                . $perl_base_instance_symlink;
        $perl_subsystem_path                    = $lib_subsystem_path
                                                . "/"
                                                . $perl_base_subsystem_dir;
    } else {
        ## Initialize subdirectory paths (CA, KRA, OCSP, TKS subsystems)
        $webapps_root_instance_path      = $webapps_instance_path
                                         . "/"
                                         . $webapps_root_base_instance_dir;
        $webapps_root_subsystem_path     = $webapps_subsystem_path
                                         . "/"
                                         . $webapps_root_base_subsystem_dir;
        $webapps_subsystem_instance_path = $webapps_instance_path
                                         . "/" . $subsystem_type;
        $webinf_instance_path            = $webapps_instance_path
                                         . "/" . $subsystem_type
                                         . "/" . $webinf_base_instance_dir;
        $webinf_subsystem_path           = $webapps_subsystem_path
                                         . "/" . $subsystem_type
                                         . "/" . $webinf_base_instance_dir;
        $webinf_lib_instance_path        = $webinf_instance_path
                                         . "/" . $lib_base_instance_dir;
        $java_pki_flavor_jar_path           = $default_java_path
                                            . "/" . $pki_flavor;
        $catalina_sh_instance_file_path    = $default_system_user_binaries
                                           . "/" . $catalina_sh_base_name
                                           . "-" . $pki_instance_name;
        $catalina_sh_subsystem_file_path   = $conf_subsystem_path
                                           . "/" . $catalina_sh_base_name;
        $certsrv_jar_file_path             = $java_pki_flavor_jar_path
                                           . "/" . $certsrv_jar_base_name;
        $certsrv_jar_symlink_path          = $webinf_lib_instance_path
                                           . "/" . $certsrv_jar_base_name;
        $nsutil_jar_file_path              = $java_pki_flavor_jar_path
                                           . "/" . $nsutil_jar_base_name;
        $nsutil_jar_symlink_path           = $webinf_lib_instance_path
                                           . "/" . $nsutil_jar_base_name;
        $cmsutil_jar_file_path              = $java_pki_flavor_jar_path
                                           . "/" . $cmsutil_jar_base_name;
        $cmsutil_jar_symlink_path           = $webinf_lib_instance_path
                                           . "/" . $cmsutil_jar_base_name;
        $cms_jar_file_path                 = $java_pki_flavor_jar_path
                                           . "/" . $cms_jar_base_name;
        $cms_jar_symlink_path              = $webinf_lib_instance_path
                                           . "/" . $cms_jar_base_name;
        $cmsbundle_jar_file_path           = $java_pki_flavor_jar_path
                                           . "/" . $cmsbundle_jar_base_name;
        $cmsbundle_jar_symlink_path        = $webinf_lib_instance_path
                                           . "/" . $cmsbundle_jar_base_name;
        $cmscore_jar_file_path             = $java_pki_flavor_jar_path
                                           . "/" . $cmscore_jar_base_name;
        $cmscore_jar_symlink_path          = $webinf_lib_instance_path
                                           . "/" . $cmscore_jar_base_name;
        $index_html_instance_file_path     = $webapps_root_instance_path
                                           . "/" . $index_html_base_name;
        $index_html_subsystem_file_path    = $webapps_root_subsystem_path
                                           . "/" . $index_html_base_name;
        $osutil_jar_file_path              = $default_system_jni_java_path
                                           . "/" . $osutil_jar_base_name;
        $osutil_jar_symlink_path           = $webinf_lib_instance_path
                                           . "/" . $osutil_jar_base_name;
        $server_xml_subsystem_file_path    = $conf_subsystem_path
                                           . "/" . $server_xml_base_name;
        $servercertnick_conf_subsystem_file_path    = $conf_subsystem_path
                                           . "/" . $servercertnick_conf_base_name;
        $subsystem_jar_file_path           = $default_java_path
                                           . "/" . $subsystem_type . ".jar";
        $subsystem_jar_symlink_path        = $webinf_lib_instance_path
                                           . "/" . $subsystem_type . ".jar";
        $tomcat5_conf_subsystem_file_path  = $conf_subsystem_path
                                           . "/" . $tomcat5_conf_base_name;
        $velocity_prop_instance_file_path  = $webinf_instance_path
                                           . "/" . $velocity_prop_base_name;
        $velocity_prop_subsystem_file_path = $webinf_subsystem_path
                                           . "/" . $velocity_prop_base_name;
        $web_xml_instance_file_path        = $webinf_instance_path
                                           . "/" . $web_xml_base_name;
        $web_xml_subsystem_file_path       = $webinf_subsystem_path
                                           . "/" . $web_xml_base_name;
    }
}


# no args
# no return value
sub initialize_paths()
{
    initialize_subsystem_paths();
    initialize_instance_paths();
    initialize_instance_symlink_paths();
    initialize_subdirectory_paths();
}


# no args
# no return value
sub initialize_pki_creation_values()
{
    # obtain the fully-qualified domain name of this host
    $host = get_FQDN( $hostname );

    # we need the certdb password generated now ...
    $db_password = generate_random( $db_password_low, $db_password_high );

    # generate a random value for a pin ...
    $random = generate_random_string( 20 );
}


# no args
# return 1 - success, or
# return 0 - failure
sub process_pki_directories()
{
    my $result = 0;
    my $remove_dir="";

    emit( "Processing PKI directories for '$pki_instance_path' ...\n" );

    ## Populate instance directory paths (instance independent)
    $result = copy_directory( $alias_subsystem_path,
                              $alias_instance_path );
    if( !$result ) {
        emit( "Failed to copy directory $alias_subsystem_path to $alias_instance_path ...\n" );
        return 0;
    }

    # Check for an optionally redirected "conf" directory path ...
    if( $redirected_conf_path eq "" ) {
        $noise_instance_file_path         = $conf_instance_path
                                          . "/" . $noise_base_name;
        $password_conf_instance_file_path = $conf_instance_path
                                          . "/" . $password_conf_base_name;
        $pfile_instance_file_path         = $conf_instance_path
                                          . "/" . $pfile_base_name;
        $pki_cfg_instance_file_path       = $conf_instance_path
                                          . "/" . $pki_cfg_base_name;

        if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
            $httpd_conf_instance_file_path = "$conf_instance_path"
                                           . "/" . $httpd_conf_base_name;
            $magic_instance_file_path      = "$conf_instance_path"
                                           . "/" . $magic_base_name;
            $mime_types_instance_file_path = $conf_instance_path
                                           . "/" . $mime_types_base_name;
            $nss_conf_instance_file_path   = "$conf_instance_path"
                                           . "/" . $nss_conf_base_name;
            $perl_conf_instance_file_path  = "$conf_instance_path"
                                           . "/" . $perl_conf_base_name;
            $pwcache_conf_instance_file_path = $conf_instance_path
                                             . "/" . $pwcache_conf_base_name;

            # create instance directory
            $result = create_directory( $conf_instance_path );
            if( !$result ) {
                emit( "Failed to create directory $conf_instance_path ...\n" );
                return 0;
            }

            # only copy selected files
            $result = copy_file( $magic_subsystem_file_path,
                                 $magic_instance_file_path );
            if( !$result ) {
                emit( "Failed to copy file $magic_subsystem_file_path to $magic_instance_file_path ...\n" );
                return 0;
            }

            $result = copy_file( $mime_types_subsystem_file_path,
                                 $mime_types_instance_file_path );
            if( !$result ) {
                emit( "Failed to copy file $mime_types_subsystem_file_path to $mime_types_instance_file_path ...\n" );
                return 0;
            }

            # fix permissions
            if( !is_Windows() ) {
                chmod( $default_file_permissions,
                       $magic_instance_file_path );
                chmod( $default_file_permissions,
                       $mime_types_instance_file_path );
            }
        } else {
            $server_xml_instance_file_path   = $conf_instance_path
                                             . "/" . $server_xml_base_name;
            $servercertnick_conf_instance_file_path   = $conf_instance_path
                                             . "/" . $servercertnick_conf_base_name;
            $tomcat5_conf_instance_file_path = $conf_instance_path
                                             . "/" . $tomcat5_conf_base_name;

            $result = copy_directory( $conf_subsystem_path,
                                      $conf_instance_path );
            if( !$result ) {
                emit( "Failed to copy directory $conf_subsystem_path to $conf_instance_path ...\n" );
                return 0;
            }
        }
    } else {
        $noise_instance_file_path         = $redirected_conf_path
                                          . "/" . $noise_base_name;
        $password_conf_instance_file_path = $redirected_conf_path
                                          . "/" . $password_conf_base_name;
        $pfile_instance_file_path         = $redirected_conf_path
                                          . "/" . $pfile_base_name;
        $pki_cfg_instance_file_path       = $redirected_conf_path
                                          . "/" . $pki_cfg_base_name;

        # Populate optionally redirected instance directory path
        # and setup a symlink in the standard area
        if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
            $httpd_conf_instance_file_path = "$redirected_conf_path"
                                           . "/" . $httpd_conf_base_name;
            $magic_instance_file_path      = "$redirected_conf_path"
                                           . "/" . $magic_base_name;
            $mime_types_instance_file_path = $redirected_conf_path
                                           . "/" . $mime_types_base_name;
            $nss_conf_instance_file_path   = "$redirected_conf_path"
                                           . "/" . $nss_conf_base_name;
            $perl_conf_instance_file_path  = "$redirected_conf_path"
                                           . "/" . $perl_conf_base_name;
            $pwcache_conf_instance_file_path = $redirected_conf_path
                                             . "/" . $pwcache_conf_base_name;

            # create redirected instance directory
            $result = create_directory( $redirected_conf_path );
            if( !$result ) {
                emit( "Failed to create directory $redirected_conf_path ...\n" );
                return 0;
            }

            # only copy selected files
            $result = copy_file( $magic_subsystem_file_path,
                                 $magic_instance_file_path );
            if( !$result ) {
                emit( "Failed to copy file $magic_subsystem_file_path to $magic_instance_file_path ...\n" );
                return 0;
            }

            $result = copy_file( $mime_types_subsystem_file_path,
                                 $mime_types_instance_file_path );
            if( !$result ) {
                emit( "Failed to copy file $mime_types_subsystem_file_path to $mime_types_instance_file_path ...\n" );
                return 0;
            }

            # fix permissions
            if( !is_Windows() ) {
                chmod( $default_file_permissions,
                       $magic_instance_file_path );
                chmod( $default_file_permissions,
                       $mime_types_instance_file_path );
            }
        } else {
            $server_xml_instance_file_path   = $redirected_conf_path
                                             . "/" . $server_xml_base_name;
            $servercertnick_conf_instance_file_path   = $redirected_conf_path
                                             . "/" . $servercertnick_conf_base_name;
            $tomcat5_conf_instance_file_path = $redirected_conf_path
                                             . "/" . $tomcat5_conf_base_name;

            $result = copy_directory( $conf_subsystem_path,
                                      $redirected_conf_path );
            if( !$result ) {
                emit( "Failed to copy directory $conf_subsystem_path to $redirected_conf_path ...\n" );
                return 0;
            }
        }

        push( @installed_stray_directories,
              $redirected_conf_path );

        $result = create_symbolic_link( $conf_instance_symlink_path,
                                        $redirected_conf_path );
        if( !$result ) {
            emit( "Failed to create symlink $conf_instance_symlink_path ...\n" );
            return 0;
        }

        $result = give_symbolic_link_to( $conf_instance_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$conf_instance_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        give_directory_to( $redirected_conf_path,
                           $pki_user,
                           $pki_group );
    }


    # Check for an optionally redirected "logs" directory path ...
    if( $redirected_logs_path eq "" ) {
        if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
            # create instance directory
            $result = create_directory( $logs_instance_path );
            if( !$result ) {
                emit( "Failed to create directory $logs_instance_path ...\n" );
                return 0;
            }
        }

        $result = copy_directory( $logs_subsystem_path,
                                  $logs_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $logs_subsystem_path to $logs_instance_path ...\n" );
            return 0;
        }

        ## (CA, KRA, OCSP, TKS instances)
        if( $subsystem_type ne $RA ) {
            ## Create a "signedAudit" directory
            $result = create_directory( "$logs_instance_path/$signed_audit_base_instance_dir" );
            if( !$result ) {
                emit( "Failed to create directory $logs_instance_path/$signed_audit_base_instance_dir ...\n" );
                return 0;
            }

            ## Fix permissions of "signedAudit" directory
            chmod( $default_dir_permissions,
                   "$logs_instance_path/$signed_audit_base_instance_dir" );
        }
    } else {
        if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
            # create redirected instance directory
            $result = create_directory( $redirected_logs_path );
            if( !$result ) {
                emit( "Failed to create directory $redirected_logs_path ...\n" );
                return 0;
            }
        }

        # Populate optionally redirected instance directory path
        # and setup a symlink in the standard area
        $result = copy_directory( $logs_subsystem_path,
                                  $redirected_logs_path );
        if( !$result ) {
            emit( "Failed to copy directory $logs_subsystem_path to $redirected_logs_path ...\n" );
            return 0;
        }

        ## (CA, KRA, OCSP, TKS instances)
        if( $subsystem_type ne $RA ) {
            ## Create a "signedAudit" directory
            $result = create_directory( "$redirected_logs_path/$signed_audit_base_instance_dir" );
            if( !$result ) {
                emit( "Failed to create directory $redirected_logs_path/$signed_audit_base_instance_dir ...\n" );
                return 0;
            }

            ## Fix permissions of "signedAudit" directory
            chmod( $default_dir_permissions,
                   "$redirected_logs_path/$signed_audit_base_instance_dir" );
        }

        push( @installed_stray_directories,
              $redirected_logs_path );

        $result = create_symbolic_link( $logs_instance_symlink_path,
                                        $redirected_logs_path );
        if( !$result ) {
            emit( "Failed to create symlink $logs_instance_symlink_path ...\n" );
            return 0;
        }

        $result = give_symbolic_link_to( $logs_instance_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$logs_instance_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        give_directory_to( $redirected_logs_path,
                           $pki_user,
                           $pki_group );
    }


    ## Populate instance directory paths (CA instances)
    if( $subsystem_type eq $CA ) {
        $result = copy_directory( $emails_subsystem_path,
                                  $emails_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $emails_subsystem_path to $emails_instance_path ...\n" );
            return 0;
        }
    }


    ## Populate instance directory paths (RA, TPS instances)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {

        if( $subsystem_type eq $TPS ) {
            $result = create_directory( $bin_instance_path );
            if( !$result ) {
                emit( "Failed to create directory $bin_instance_path ...\n" );
                return 0;
            }
        }

        $result = create_directory( $lib_instance_path );
        if( !$result ) {
            emit( "Failed to create directory $lib_instance_path ...\n" );
            return 0;
        }

        $result = create_directory( $scripts_instance_path );
        if( !$result ) {
            emit( "Failed to create directory $scripts_instance_path ...\n" );
            return 0;
        }

        # Apache Specific
        if( $subsystem_type eq $TPS ) {
            $result = copy_directory( $cgibin_subsystem_path,
                                      $cgibin_instance_path );
            if( !$result ) {
                emit( "Failed to copy directory $cgibin_subsystem_path ...\n" );
                return 0;
            }
        }

        # Apache Specific
        $result = copy_directory( $docroot_subsystem_path,
                                  $docroot_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $docroot_subsystem_path ...\n" );
            return 0;
        }

        $result = copy_directory( $ui_subsystem_path,
                                  $pki_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $ui_subsystem_path ...\n" );
            return 0;
        }

        # fix permissions
        if( !is_Windows() ) {
            # Apache Specific
            if( $subsystem_type eq $TPS ) {
                chmod( $default_dir_permissions,
                       "$cgibin_instance_path/demo" );
                chmod( $default_exe_permissions,
                       "$cgibin_instance_path/demo/*.cgi" );
                chmod( $default_file_permissions,
                       "$cgibin_instance_path/demo/*.html" );
                chmod( $default_dir_permissions,
                       "$cgibin_instance_path/home" );
                chmod( $default_exe_permissions,
                       "$cgibin_instance_path/home/*.cgi" );
                chmod( $default_file_permissions,
                       "$cgibin_instance_path/home/*.html" );
                chmod( $default_dir_permissions,
                       "$cgibin_instance_path/so" );
                chmod( $default_exe_permissions,
                       "$cgibin_instance_path/so/*.cgi" );
                chmod( $default_file_permissions,
                       "$cgibin_instance_path/so/*.html" );
                chmod( $default_dir_permissions,
                       "$cgibin_instance_path/sow" );
                chmod( $default_exe_permissions,
                       "$cgibin_instance_path/sow/*.cgi" );
                chmod( $default_file_permissions,
                       "$cgibin_instance_path/sow/*.html" );
                chmod( $default_exe_permissions,
                       "$cgibin_instance_path/sow/*.pl" );
            }

            # Apache Specific
            chmod( $default_file_permissions,
                   "$docroot_instance_path/GenericAuth.html" );
            chmod( $default_file_permissions,
                   "$docroot_instance_path/style.css" );
        }
    } else {
        ## Populate instance directory paths (CA, KRA, OCSP, TKS instances)
        $result = copy_directory( $acl_subsystem_path,
                                  $acl_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $acl_subsystem_path ...\n" );
            return 0;
        }

        $result = copy_directory( $profiles_subsystem_path,
                                  $profiles_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $profiles_subsystem_path ...\n" );
            return 0;
        }

        $result = copy_directory( $webapps_subsystem_path,
                                  $webapps_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $webapps_subsystem_path ...\n" );
            return 0;
        }

        $result = copy_directory( $common_ui_subsystem_path,
                                  $webapps_subsystem_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $webapps_subsystem_path ...\n" );
            return 0;
        }

        $result = copy_directory( $ui_subsystem_path,
                                  $pki_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $webapps_subsystem_path ...\n" );
            return 0;
        }
        
        ##
        # Tomcat Specific
        $result = copy_directory( $shared_subsystem_path,
                                  $shared_instance_path );
        if( !$result ) {
            emit( "Failed to copy directory $shared_subsystem_path ...\n" );
            return 0;
        }

        $result = create_directory( $temp_instance_path );
        if( !$result ) {
            emit( "Failed to create directory $temp_instance_path ...\n" );
            return 0;
        }

        $result = create_directory( $work_instance_path );
        if( !$result ) {
            emit( "Failed to create directory $work_instance_path ...\n" );
            return 0;
        }
    }

    ## Set appropriate permissions
    give_directory_to( $pki_instance_path,
                       $pki_user,
                       $pki_group );

    return 1;
}


# arg0 source file path
# arg1 dest file path
# arg2 %slot_hash
# return 1 - success, or
# return 0 - failure
sub process_file_template
{
    my( $source_file_path ) = $_[0];
    my( $dest_file_path ) = $_[1];
    my( $l_slot_hash ) = $_[2];

    my $result = 0;
    my $inf = new FileHandle;
    my $buff = "";
    my $ouf = new FileHandle;

    emit( "    Converting '$source_file_path' ==> '$dest_file_path' ...\n" );

    # check for a valid source file
    if( !is_path_valid( $source_file_path ) ) {
        emit( "process_file_template():  invalid source path "
            . "$source_file_path!\n",
              "error" );
        return $result;
    }

    # check for a valid destination file
    if( !is_path_valid( $dest_file_path ) ) {
        emit( "process_file_template():  invalid destination path "
            . "$dest_file_path!\n",
              "error" );
        return $result;
    }

    # read in contents of source file
    $inf->open( "<$source_file_path" ) or
    die "Could not open $source_file_path\n";
    while( <$inf> ) {
        my $line = $_;
        chomp( $line );
        $buff = $buff . "$line\n";
    }
    $inf->close();


    # process each line substituting each [KEY]
    # with its corresponding slot hash value
    while( my( $key, $value ) = each( %$l_slot_hash ) ) {
        if( $key eq $PKI_CERT_DB_PASSWORD_SLOT ) {
            # Although this is nothing more than a random number
            # used for initialization, for consistency, as with ALL
            # other password/pin values (with one notable EXCEPTION),
            # the word "(sensitive)" is printed out rather than the
            # contents of "$value".
            emit( "        replacing: $key with: (sensitive)\n" );
        } else {
            emit( "        replacing: $key with: $value\n" );
        }
        $buff =~ s/\[$key\]/$value/g;
    }


    # write out these modified contents to the destination file
    $ouf->open( ">$dest_file_path" ) or die "Could not open $dest_file_path\n";
    $ouf->print( $buff );
    $ouf->close();

    $result = 1;

    return $result;
}


# no args
# return 1 - success, or
# return 0 - failure
sub process_pki_templates()
{
    my $use_port_separation = 0;
    if( $agent_secure_port >= 0 &&
        ( $subsystem_type ne $RA ) &&
        ( $subsystem_type ne $TPS ) ) {
        $use_port_separation = 1;
    }
 
    my %slot_hash = ();

    emit( "Processing PKI templates for '$pki_instance_path' ...\n" );

    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
        # Setup templates (RA, TPS)
        $slot_hash{$GROUPID}               = $pki_group;
        $slot_hash{$HTTPD_CONF}            = $httpd_conf_instance_file_path;
        $slot_hash{$INSTANCE_ID}           = $pki_instance_name;
        $slot_hash{$INSTANCE_ROOT}         = $pki_instance_root;
        $slot_hash{$LIB_PREFIX}            = $lib_prefix;
        $slot_hash{$NSS_CONF}              = $nss_conf_instance_file_path;
        $slot_hash{$OBJ_EXT}               = $obj_ext;
        $slot_hash{$PORT}                  = $unsecure_port;
        $slot_hash{$PROCESS_ID}            = $$;
        $slot_hash{$SECURE_PORT}           = $secure_port;
        $slot_hash{$NON_CLIENTAUTH_SECURE_PORT} = $non_clientauth_secure_port;
        $slot_hash{$SECURITY_LIBRARIES}    = $default_security_libraries;
        $slot_hash{$SERVER_NAME}           = $host;
        $slot_hash{$SERVER_ROOT}           = $pki_instance_path;
        $slot_hash{$SUBSYSTEM_TYPE}        = $subsystem_type;
        $slot_hash{$SYSTEM_LIBRARIES}      = $default_system_libraries;
        $slot_hash{$SYSTEM_USER_LIBRARIES} = $default_system_user_libraries;
        $slot_hash{$TMP_DIR}               = $tmp_dir;
        $slot_hash{$TPS_DIR}               = $pki_subsystem_path;
        $slot_hash{$USERID}                = $pki_user;
        $slot_hash{$PKI_FLAVOR}            = $pki_flavor;
        $slot_hash{$PKI_RANDOM_NUMBER_SLOT}    = $random;
        $slot_hash{$REQUIRE_CFG_PL}        = "require \""
                                           . $cgi_sow_instance_cfg_pl_path
                                           . "\";";
        if( is_Fedora() || (is_RHEL() && (! is_RHEL4())) ) {
            $slot_hash{$FORTITUDE_APACHE}  = "Apache2";
            $slot_hash{$FORTITUDE_DIR}     = "/usr";
            $slot_hash{$FORTITUDE_LIB_DIR} = "/etc/httpd";
            $slot_hash{$FORTITUDE_MODULE}  = "/etc/httpd/modules";
            $slot_hash{$FORTITUDE_AUTH_MODULES} =
"
LoadModule auth_basic_module /etc/httpd/modules/mod_auth_basic.so
LoadModule authn_file_module /etc/httpd/modules/mod_authn_file.so
LoadModule authz_user_module /etc/httpd/modules/mod_authz_user.so
LoadModule authz_groupfile_module /etc/httpd/modules/mod_authz_groupfile.so
LoadModule authz_host_module /etc/httpd/modules/mod_authz_host.so
";
            $slot_hash{$FORTITUDE_NSS_MODULES} =
"
LoadModule nss_module  /etc/httpd/modules/libmodnss.so
";
        }
        else {
            $slot_hash{$FORTITUDE_APACHE}  = "Apache";
            $slot_hash{$FORTITUDE_DIR}     = "/opt/fortitude";
            $slot_hash{$FORTITUDE_LIB_DIR} = "/opt/fortitude";
            $slot_hash{$FORTITUDE_MODULE}  = "/opt/fortitude/modules.local";
            $slot_hash{$FORTITUDE_AUTH_MODULES} =
"
LoadModule auth_module /opt/fortitude/modules/mod_auth.so
LoadModule access_module /opt/fortitude/modules/mod_access.so
";
            $slot_hash{$FORTITUDE_NSS_MODULES} =
"
LoadModule nss_module  /opt/fortitude/modules.local/libmodnss.so
";
        }
    } else {
        # Setup templates (CA, KRA, OCSP, TKS)
        $slot_hash{$INSTALL_TIME}              = localtime;
        $slot_hash{$PKI_CERT_DB_PASSWORD_SLOT} = $db_password;
        $slot_hash{$PKI_CFG_PATH_NAME_SLOT}    = $pki_cfg_instance_file_path;
        $slot_hash{$PKI_GROUP_SLOT}            = $pki_group;
        $slot_hash{$PKI_INSTANCE_ID_SLOT}      = $pki_instance_name;
        $slot_hash{$PKI_INSTANCE_PATH_SLOT}    = $pki_instance_path;
        $slot_hash{$PKI_INSTANCE_ROOT_SLOT}    = $pki_instance_root;
        $slot_hash{$PKI_MACHINE_NAME_SLOT}     = $host;
        $slot_hash{$PKI_RANDOM_NUMBER_SLOT}    = $random;
        $slot_hash{$PKI_SERVER_XML_CONF}       = $server_xml_instance_file_path;
        $slot_hash{$PKI_SUBSYSTEM_TYPE_SLOT}   = $subsystem_type;
        $slot_hash{$PKI_UNSECURE_PORT_SLOT}    = $unsecure_port;

        # Define "Port Separation" (default) versus "Shared Ports" (legacy)
        if( $use_port_separation) 
        {
            # Establish "Port Separation" Connector Names
            $slot_hash{$PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT}     = $PKI_UNSECURE_PORT_NAME;
            $slot_hash{$PKI_SECURE_PORT_CONNECTOR_NAME_SLOT}       = $PKI_AGENT_SECURE_PORT_NAME;
            $slot_hash{$PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_ADMIN_SECURE_PORT_NAME;
            $slot_hash{$PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT}    = $PKI_EE_SECURE_PORT_NAME;
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT}    = $PKI_EE_SECURE_CLIENT_AUTH_PORT_NAME;

            # Establish "Port Separation" Connector Ports
            $slot_hash{$PKI_SECURE_PORT_SLOT}       = $agent_secure_port;
            $slot_hash{$PKI_AGENT_SECURE_PORT_SLOT} = $agent_secure_port;
            $slot_hash{$PKI_EE_SECURE_PORT_SLOT}    = $ee_secure_port; 
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT}    = $ee_secure_client_auth_port; 
            $slot_hash{$PKI_ADMIN_SECURE_PORT_SLOT} = $admin_secure_port;

            # Comment "Port Separation" appropriately
            $slot_hash{$PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT}     = $PKI_UNSECURE_SEPARATE_PORTS_COMMENT;
            $slot_hash{$PKI_SECURE_PORT_COMMENT_SERVER_SLOT}       = $PKI_AGENT_SECURE_SEPARATE_PORTS_COMMENT;
            $slot_hash{$PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT} = $PKI_ADMIN_SECURE_SEPARATE_PORTS_COMMENT;
            $slot_hash{$PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT}    = $PKI_EE_SECURE_SEPARATE_PORTS_COMMENT;
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT}    = $PKI_EE_SECURE_CLIENT_AUTH_SEPARATE_PORTS_COMMENT;

            # Set appropriate "clientAuth" parameter for "Port Separation"
            $slot_hash{$PKI_AGENT_CLIENTAUTH_SLOT} = "true";

            # Do NOT comment out the "Admin/EE" Ports
            $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT}  = "";
            $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = "";

            # Do NOT comment out the "Admin/Agent/EE" Filters
            # used by Port Separation
            $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT}  = "";
            $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT} = "";
        } else {
            # Establish "Shared Ports" Connector Names
            $slot_hash{$PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT}     = $PKI_UNSECURE_PORT_NAME;
            $slot_hash{$PKI_SECURE_PORT_CONNECTOR_NAME_SLOT}       = $PKI_SECURE_PORT_NAME;
            $slot_hash{$PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT} = $PKI_UNUSED_SECURE_PORT_NAME;
            $slot_hash{$PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT}    = $PKI_UNUSED_SECURE_PORT_NAME;
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT}    = $PKI_UNUSED_SECURE_PORT_NAME;

            # Establish "Shared Ports" Connector Ports
            $slot_hash{$PKI_SECURE_PORT_SLOT}       = $secure_port;
            $slot_hash{$PKI_AGENT_SECURE_PORT_SLOT} = $secure_port;
            $slot_hash{$PKI_EE_SECURE_PORT_SLOT}    = $secure_port; 
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT}    = $secure_port; 
            $slot_hash{$PKI_ADMIN_SECURE_PORT_SLOT} = $secure_port;

            # Comment "Shared Ports" appropriately
            $slot_hash{$PKI_UNSECURE_PORT_COMMENT_SERVER_SLOT}     = $PKI_UNSECURE_SHARED_PORTS_COMMENT;
            $slot_hash{$PKI_SECURE_PORT_COMMENT_SERVER_SLOT}       = $PKI_SECURE_SHARED_PORTS_COMMENT;
            $slot_hash{$PKI_ADMIN_SECURE_PORT_COMMENT_SERVER_SLOT} = "";
            $slot_hash{$PKI_EE_SECURE_PORT_COMMENT_SERVER_SLOT}    = "";
            $slot_hash{$PKI_EE_SECURE_CLIENT_AUTH_PORT_COMMENT_SERVER_SLOT}    = "";

            # Set appropriate "clientAuth" parameter for "Shared Ports"
            $slot_hash{$PKI_AGENT_CLIENTAUTH_SLOT} = "agent";

            # Comment out the "Admin/EE" Ports
            $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_SERVER_SLOT}  = $PKI_OPEN_COMMENT;
            $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_SERVER_SLOT} = $PKI_CLOSE_COMMENT;;

            # Comment out the "Admin/Agent/EE" Filters
            $slot_hash{$PKI_OPEN_SEPARATE_PORTS_COMMENT_WEB_SLOT}  = $PKI_OPEN_COMMENT;
            $slot_hash{$PKI_CLOSE_SEPARATE_PORTS_COMMENT_WEB_SLOT} = $PKI_CLOSE_COMMENT;
        } 

        $slot_hash{$PKI_WEBAPPS_NAME}          = $webapps_base_subsystem_dir; 
        $slot_hash{$PKI_USER_SLOT}             = $pki_user;
        $slot_hash{$TOMCAT_SERVER_PORT_SLOT}   = $tomcat_server_port;
        $slot_hash{$PKI_FLAVOR_SLOT}           = $pki_flavor;
    }


    ## Process templates (instance independent)
    #
    #  NOTE:  The values substituted may differ across subsystems.
    #

    # process "CS.cfg" template
    $result = process_file_template( $pki_cfg_subsystem_file_path,
                                     $pki_cfg_instance_file_path,
                                     \%slot_hash );
    if( !$result ) {
        return 0;
    }

    # fix ownership for "CS.cfg"
    $result = give_file_to( $pki_cfg_instance_file_path,
                            $pki_user,
                            $pki_group );
    if( !$result ) {
        emit( "Can't change ownership of $pki_cfg_instance_file_path.\n",
              "error" );
        return 0;
    }

    chmod( $default_file_permissions,
           $pki_cfg_instance_file_path );

    if( $^O eq "linux" ) {
        # process "config.desktop" template
        $result = process_file_template( $setup_config_subsystem_file_path,
                                         $setup_config_instance_file_path,
                                         \%slot_hash );
        if( ! $result ) {
            return 0;
        }

        push( @installed_files,
              $setup_config_instance_file_path );
    }


    ## Process templates (CA instances)
    if( $subsystem_type eq $CA ) {
        # process ProfileSelect.template
        $result = process_file_template( $profile_select_template_subsystem_file_path,
                                         $profile_select_template_instance_file_path,
                                         \%slot_hash );
        if( ! $result ) {
            return 0;
        }
 
     }


    ## Process templates (RA, TPS instances)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {

        if( $subsystem_type eq $TPS ) {

          # process "apachectl" template
          $result = process_file_template( $apachectl_subsystem_file_path,
                                           $apachectl_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

          chmod( $default_exe_permissions,
                 $apachectl_instance_file_path );


          # process "cgi" template
          $result = process_file_template( $cgi_home_subsystem_file_path,
                                           $cgi_home_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

          $result = process_file_template( $cgi_demo_subsystem_file_path,
                                           $cgi_demo_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

          $result = process_file_template( $cgi_so_subsystem_file_path,
                                           $cgi_so_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

          $result = process_file_template( $cgi_so_subsystem_enroll_file_path,
                                           $cgi_so_instance_enroll_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

          # process each "*.cgi" file in subsystem "sow" directory
          opendir( SUBSYSTEM_DIR, $cgi_sow_subsystem_file_path );
          while( defined( my $entity = readdir( SUBSYSTEM_DIR ) ) ) {
              if( $entity =~ m/.cgi$/ ) {
                  # build complete "sow" subystem ".cgi" file name
                  $cgi_sow_subsystem_cgi_file_path = $cgi_sow_subsystem_file_path
                                                  . "/"
                                                  . $entity;
                  # build complete "sow" instance ".cgi" file name
                  $cgi_sow_instance_cgi_file_path = $cgi_sow_instance_file_path
                                                  . "/"
                                                  . $entity;
                  # process complete "sow" instance ".cgi" file name
                  $result = process_file_template( $cgi_sow_subsystem_cgi_file_path,
                                                   $cgi_sow_instance_cgi_file_path,
                                                   \%slot_hash );
                  if( !$result ) {
                      return 0;
                  }
              }
          }
          closedir( SUBSYSTEM_DIR );

          # process "addAgents.ldif" template
          $result = process_file_template( $addAgents_ldif_subsystem_file_path,
                                           $addAgents_ldif_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }


          # process "addIndexes.ldif" template
          $result = process_file_template( $addIndexes_ldif_subsystem_file_path,
                                           $addIndexes_ldif_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }


          # process "addTokens.ldif" template
          $result = process_file_template( $addTokens_ldif_subsystem_file_path,
                                           $addTokens_ldif_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }


          # process "addVLVIndexes.ldif" template
          $result = process_file_template(
                        $addVLVIndexes_ldif_subsystem_file_path,
                        $addVLVIndexes_ldif_instance_file_path,
                        \%slot_hash );
          if( !$result ) {
              return 0;
          }

          # process "schemaMods.ldif" template
          $result = process_file_template( $schemaMods_ldif_subsystem_file_path,
                                           $schemaMods_ldif_instance_file_path,
                                           \%slot_hash );
          if( !$result ) {
              return 0;
          }

        }


        # process "httpd.conf" template
        $result = process_file_template( $httpd_conf_subsystem_file_path,
                                         $httpd_conf_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        # fix ownership for httpd.conf
        $result = give_file_to( $httpd_conf_instance_file_path,
                                $pki_user,
                                $pki_group );
        if( !$result ) {
            emit( "Can't change ownership of "
                . "$httpd_conf_instance_file_path.\n",
                  "error" );
            return 0;
        }

        chmod( $default_file_permissions,
               $httpd_conf_instance_file_path );


        # process "nss.conf" template
        $result = process_file_template( $nss_conf_subsystem_file_path,
                                         $nss_conf_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        # fix ownership for nss.conf
        $result = give_file_to( $nss_conf_instance_file_path,
                                $pki_user,
                                $pki_group );
        if( !$result ) {
            emit( "Can't change ownership of "
                . "$nss_conf_instance_file_path.\n",
                  "error" );
            return 0;
        }

        chmod( $default_file_permissions,
               $nss_conf_instance_file_path );


        # process "perl.conf" template
        $result = process_file_template( $perl_conf_subsystem_file_path,
                                         $perl_conf_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        # fix ownership for perl.conf
        $result = give_file_to( $perl_conf_instance_file_path,
                                $pki_user,
                                $pki_group );
        if( !$result ) {
            emit( "Can't change ownership of "
                . "$perl_conf_instance_file_path.\n",
                  "error" );
            return 0;
        }

        chmod( $default_file_permissions,
               $perl_conf_instance_file_path );


        # process "nss_pcache" template
        $result = process_file_template( $nss_pcache_subsystem_file_path,
                                         $nss_pcache_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        chmod( $default_exe_permissions,
               $nss_pcache_instance_file_path );


    } else {
        ## Process templates (CA, KRA, OCSP, TKS instances)
        # process "catalina.sh" (aka dtomcat5) template
        $result = process_file_template( $catalina_sh_subsystem_file_path,
                                         $catalina_sh_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        $result = give_file_to( $catalina_sh_instance_file_path,
                                $pki_user,
                                $pki_group );
        if( !$result ) {
            emit( "Can't change ownership of "
                . "$catalina_sh_instance_file_path.\n",
                  "error" );
            return 0;
        }

        chmod( $default_exe_permissions,
               $catalina_sh_instance_file_path );

        push( @installed_files,
              $catalina_sh_instance_file_path );


        # process "index.html" template
        $result = process_file_template( $index_html_subsystem_file_path,
                                         $index_html_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }


        # process "server.xml" template
        $result = process_file_template( $server_xml_subsystem_file_path,
                                         $server_xml_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }


        # process "serverCertNick.conf" template
        $result = process_file_template( $servercertnick_conf_subsystem_file_path,
                                         $servercertnick_conf_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }

        # process "tomcat5.conf" template
        $result = process_file_template( $tomcat5_conf_subsystem_file_path,
                                         $tomcat5_conf_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }


        # process "velocity.properties" template
        $result = process_file_template( $velocity_prop_subsystem_file_path,
                                         $velocity_prop_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }


        # process "web.xml" template
        $result = process_file_template( $web_xml_subsystem_file_path,
                                         $web_xml_instance_file_path,
                                         \%slot_hash );
        if( !$result ) {
            return 0;
        }
    }

    return 1;
}


# no args
# return 1 - success, or
# return 0 - failure
sub process_pki_files_and_symlinks()
{
    my $result = 0;

    emit( "Processing PKI files and symbolic links for "
        . "'$pki_instance_path' ...\n" );

    ## Populate instances (instance independent)

    # create a filled in temporary "noise"
    # file for this instance
    my $noise = generate_random_string( 1024 );

    create_file( $noise_instance_file_path,
                 $noise );

    $result = give_file_to( $noise_instance_file_path,
                            $pki_user,
                            $pki_group );
    if( !$result ) {
        emit( "Can't change ownership of $noise_base_name.\n",
              "error" );
        return 0;
    }

    chmod( $default_file_permissions,
           $noise_instance_file_path );


    # create a filled in empty "password.conf"
    # password file for this instance
    create_file( $password_conf_instance_file_path,
                 "$default_security_token:$db_password" );

    $result = give_file_to( $password_conf_instance_file_path,
                            $pki_user,
                            $pki_group );
    if( !$result ) {
        emit( "Can't change ownership of $password_conf_base_name.\n",
              "error" );
        return 0;
    }

    chmod( $default_file_permissions,
           $password_conf_instance_file_path );


    # create a filled in empty temporary "pfile"
    # password file for this instance
    create_file( $pfile_instance_file_path,
                 $db_password );

    $result = give_file_to( $pfile_instance_file_path,
                            $pki_user,
                            $pki_group );
    if( !$result ) {
        emit( "Can't change ownership of $pfile_base_name.\n",
              "error" );
        return 0;
    }

    chmod( $default_file_permissions,
           $pfile_instance_file_path );

    # generate a local init script for this PKI instance
    my $local_pki_init_script         = new FileHandle;
    my $local_pki_init_script_name    = $pki_instance_path
                                      . "/" . $pki_instance_name;
    my $local_pki_init_script_command = "";

    # create this PKI instance's local init script
    $local_pki_init_script->open( ">$local_pki_init_script_name" ) or
    die "Could not open $local_pki_init_script_name\n";

    # publish the appropriate contents to this
    # PKI instance's local init script
    $local_pki_init_script->print( "#!/bin/bash\n" );
    $local_pki_init_script->print( "if [ \$# -ne 1 ]; then\n" );
    $local_pki_init_script->print( "    echo \"Usage: \$0 {start|stop|"
                                 . "restart|condrestart|force-restart|"
                                 . "try-restart|reload|status}\"\n" );
    $local_pki_init_script->print( "    exit 3\n" );
    $local_pki_init_script->print( "fi\n\n" );

    if( $^O eq "linux" ) {
        $local_pki_init_script_command = "/sbin/service"
                                       . " " . $pki_init_script
                                       . " " . "\$1"
                                       . " " . $pki_instance_name;
    } else {
        # default case:  e. g. - ( $^O eq "solaris" )
        $local_pki_init_script_command = $default_init_scripts_path
                                       . "/" . $pki_init_script
                                       . " " . "\$1"
                                       . " " . $pki_instance_name;
    }

    $local_pki_init_script->print( "$local_pki_init_script_command\n\n" );

    # close and save this PKI instance's local init script
    $local_pki_init_script->close();

    #
    # NOTE:  This PKI instance's local init script requires
    #        "$root_user:$root_group" ownership since the
    #        destination that it refers to is owned by
    #        "$root_user:$root_group".
    #
    $result = give_file_to( $local_pki_init_script_name,
                            $root_user,
                            $root_group );
    if( !$result ) {
        emit( "$local_pki_init_script_name ownership problems!",
              "error" );
        return 0;
    }

    chmod( $default_exe_permissions,
           $local_pki_init_script_name );

    ## Populate instances (RA, TPS instances)
    if( $subsystem_type eq $RA || $subsystem_type eq $TPS ) {
        # create an empty file called "pwcache.conf" for this instance
        create_empty_file( $pwcache_conf_instance_file_path );

        $result = give_file_to( $pwcache_conf_instance_file_path,
                                $pki_user,
                                $pki_group );
        if( !$result ) {
            emit( "Can't change ownership of $pwcache_conf_base_name.\n",
                  "error" );
            return 0;
        }

        chmod( $default_file_permissions,
               $pwcache_conf_instance_file_path );

        # Subdirectory Specific symbolic links

        # create instance symlink to subsystem "perl" subdirectory
        $result = create_symbolic_link( $perl_instance_symlink_path,
                                        $perl_subsystem_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $perl_instance_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$perl_instance_symlink_path ownership problems!",
                  "error" );
            return 0;
        }


        # Apache Specific symbolic links

        # create instance symlink to apache "run" subdirectory
        $result = create_symbolic_link( $run_instance_symlink_path,
                                        ( $default_apache_pids_path
                                        . "/" . $subsystem_type ) );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $run_instance_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$run_base_instance_symlink ownership problems!",
                  "error" );
            return 0;
        }
    } else {
        ## Populate instances (CA, KRA, OCSP, TKS instances)
        # create instance "webapps/$subsystem_type/WEB-INF/lib" subdirectory
        $result = create_directory( $webinf_lib_instance_path );
        if( !$result ) {
            return 0;
        }

        # create instance symlink to "$subsystem_type.jar"
        $result = create_symbolic_link( $subsystem_jar_symlink_path,
                                        $subsystem_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $subsystem_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$subsystem_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }


        # create instance symlink to "certsrv.jar"
        $result = create_symbolic_link( $certsrv_jar_symlink_path,
                                        $certsrv_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $certsrv_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$certsrv_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        # create instance symlink to "cmsutil.jar"
        $result = create_symbolic_link( $cmsutil_jar_symlink_path,
                                        $cmsutil_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $cmsutil_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$cms_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        # create instance symlink to "nsutil.jar"
        $result = create_symbolic_link( $nsutil_jar_symlink_path,
                                        $nsutil_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $nsutil_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$cms_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        # create instance symlink to "cms.jar"
        $result = create_symbolic_link( $cms_jar_symlink_path,
                                        $cms_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $cms_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$cms_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }


        # create instance symlink to "cmsbundle.jar"
        $result = create_symbolic_link( $cmsbundle_jar_symlink_path,
                                        $cmsbundle_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $cmsbundle_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$cmsbundle_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }


        # create instance symlink to "cmscore.jar"
        $result = create_symbolic_link( $cmscore_jar_symlink_path,
                                        $cmscore_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $cmscore_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$cmscore_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }


        # create instance symlink to "osutil.jar"
        $result = create_symbolic_link( $osutil_jar_symlink_path,
                                        $osutil_jar_file_path );
        if( !$result ) {
            return 0;
        }

        $result = give_symbolic_link_to( $osutil_jar_symlink_path,
                                         $pki_user,
                                         $pki_group );
        if( !$result ) {
            emit( "$osutil_jar_symlink_path ownership problems!",
                  "error" );
            return 0;
        }

        # Tomcat Specific

        # create instance symlink to tomcat "common" directory
        #
        # NOTE:  This symlink requires "$root_user:$root_group" ownership
        #        since the destination that it refers to is owned by
        #        "$root_user:$root_group".
        #
        $result = create_symbolic_link( $common_instance_symlink_path,
                                        $default_tomcat_common_path );
        if( !$result ) {
            return 0;
        }
        $result = give_symbolic_link_to( $common_instance_symlink_path,
                                         $root_user,
                                         $root_group );
        if( !$result ) {
            emit( "$common_instance_symlink_path ownership problems!",
                  "error" );
            return 0;
        }
    }

    return 1;
}


# no args
# return 1 - success, or
# return 0 - failure
sub process_pki_security_databases()
{
    my $result          = 0;
    my $serial_number   = 0;
    my $validity_period = 12;
    my $time_stamp      = get_time_stamp();
    my $subject         = "CN=$host,O=$time_stamp";
    my $issuer_name     = "CN=$host,O=$time_stamp";
    my $nickname        = "Server-Cert cert-$pki_instance_name";
    my $trustargs       = "CTu,CTu,CTu";

    emit( "Processing PKI security databases for '$pki_instance_path' ...\n" );

    # now create and configure pki security databases,
    # cert3.db, key3.db, secmod.db ...
    if( !file_exists( $default_certutil_command ) ) {
        emit( "process_pki_security_databases():  $default_certutil_command "
            . "does not exist!\n",
              "error" );
        return $result;

    }

    if( !file_exists( $noise_instance_file_path ) ) {
        emit( "process_pki_security_databases():  Can't find "
            . "temp noise file!\n",
              "error" );
        return $result;
    }

    if( !file_exists( $pfile_instance_file_path ) ) {
        emit( "process_pki_security_databases():  Can't find temp file "
            . "with password!\n",
              "error" );
        return $result;
    }

    certutil_create_databases( $alias_instance_path,
                               $pfile_instance_file_path );

    certutil_generate_self_signed_cert( $alias_instance_path,
                                        $default_security_token,
                                        $serial_number,
                                        $validity_period,
                                        $subject,
                                        $issuer_name,
                                        $nickname,
                                        $trustargs,
                                        $noise_instance_file_path,
                                        $pfile_instance_file_path );

    remove_file( $noise_instance_file_path );

    remove_file( $pfile_instance_file_path );

    give_directory_to( $alias_instance_path, $pki_user, $pki_group );

    return 1;
}


# no args
# return 1 - success, or
# return 0 - failure
sub process_pki_security_modules()
{
    my $result = 0;

    emit( "Processing PKI security modules for '$pki_instance_path' ...\n" );

    if( !file_exists( $default_modutil_command ) ) {
        emit( "process_pki_security_modules():  $default_modutil_command "
            . "must be installed on system!\n",
              "error" );
        return $result;
    }

    emit( "    Attempting to add hardware security modules to system if "
        . "applicable ...\n" );

    while( my( $key, $value ) = each( %supported_sec_modules_hash ) ) {
        if( !file_exists( $value ) ) {
            emit( "        module name: $key  lib: $value DOES NOT EXIST!\n" );
            next;
        } else {
            modutil_add_token( $alias_instance_path, $key, $value );
            emit( "        Added module name: $key  lib: $value\n" );
        }
    }

    return 1;
}

# no args
# return 1 - success, or
# return 0 - failure
sub build_pki_registry_subsystem_path()
{
    my $result = 0;

    # Establish PKI subsystem-level registry
    $pki_registry_subsystem_path = $pki_registry_path
                                 . "/" . $subsystem_type;

    if( !directory_exists( "$pki_registry_subsystem_path" ) ) {
        # create pki registry for this subsystem
        $result = create_directory( "$pki_registry_subsystem_path" );
        if( !$result ) {
            emit( "Failed to create directory "
                . "$pki_registry_subsystem_path ...\n" );
            return 0;
        }
    }

    return 1;
}

# no args
# return 1 - success, or
# return 0 - failure
sub construct_pki_instance_registry()
{
    my $result = 0;

    # generate a registry entry for this PKI instance
    $pki_instance_registry       = new FileHandle;
    $pki_instance_registry_entry = $pki_registry_subsystem_path
                                 . "/" . $pki_instance_name;

    # create this PKI instance's registry entry
    $pki_instance_registry->open( ">$pki_instance_registry_entry" ) or
    die "Could not open $pki_instance_registry_entry\n";

    # publish the appropriate contents to this PKI instance's registry entry
    if( $subsystem_type eq $CA   ||
        $subsystem_type eq $KRA  ||
        $subsystem_type eq $OCSP ||
        $subsystem_type eq $TKS ) {
        $pki_instance_registry->print( "# Establish PKI Variable \"Slot\" "
                                     . "Substitutions\n\n" );
        $pki_instance_registry->print( "PKI_FLAVOR=$pki_flavor\n" );
        $pki_instance_registry->print( "export PKI_FLAVOR\n\n" );
        $pki_instance_registry->print( "PKI_GROUP=$pki_group\n" );
        $pki_instance_registry->print( "export PKI_GROUP\n\n" );
        $pki_instance_registry->print( "PKI_INSTANCE_ID=$pki_instance_name\n" );
        $pki_instance_registry->print( "export PKI_INSTANCE_ID\n\n" );
        $pki_instance_registry->print( "PKI_INSTANCE_PATH="
                                     . "$pki_instance_path\n" );
        $pki_instance_registry->print( "export PKI_INSTANCE_PATH\n\n" );
        $pki_instance_registry->print( "PKI_SERVER_XML_CONF="
                                     . "$server_xml_instance_file_path\n" );
        $pki_instance_registry->print( "export PKI_SERVER_XML_CONF\n\n" );
        $pki_instance_registry->print( "PKI_SUBSYSTEM_TYPE=$subsystem_type\n" );
        $pki_instance_registry->print( "export PKI_SUBSYSTEM_TYPE\n\n" );
        $pki_instance_registry->print( "PKI_USER=$pki_user\n" );
        $pki_instance_registry->print( "export PKI_USER\n\n" );
        $pki_instance_registry->print( "# Use CATALINA_BASE\n\n" );
        $pki_instance_registry->print( "CATALINA_BASE="
                                     . "\${PKI_INSTANCE_PATH}\n" );
        $pki_instance_registry->print( "export CATALINA_BASE\n\n" );
        $pki_instance_registry->print( "# Get Tomcat config\n\n" );
        $pki_instance_registry->print( "TOMCAT_CFG=\"\${PKI_INSTANCE_PATH}/"
                                     . "conf/tomcat5.conf\"\n" );
        $pki_instance_registry->print( "export TOMCAT_CFG\n\n" );
        $pki_instance_registry->print( "[ -r \"\$TOMCAT_CFG\" ] && "
                                     . ". \"\${TOMCAT_CFG}\"\n\n" );
        $pki_instance_registry->print( "# Path to the tomcat launch script "
                                     . "(direct don't use wrapper)\n" );
        $pki_instance_registry->print( "TOMCAT_SCRIPT=/usr/bin/"
                                     . "dtomcat5-\${PKI_INSTANCE_ID}\n" );
        $pki_instance_registry->print( "export TOMCAT_SCRIPT\n\n" );
        $pki_instance_registry->print( "# Path to the script that will "
                                     . "refresh jar symlinks on startup\n" );
        $pki_instance_registry->print( "if [ \${OS} = \"Linux\" ] ; then\n" );
        $pki_instance_registry->print( "    TOMCAT_RELINK_SCRIPT=\"/usr/share/"
                                     . "tomcat5/bin/relink\"\n" );
        $pki_instance_registry->print( "    export TOMCAT_RELINK_SCRIPT\n" );
        $pki_instance_registry->print( "fi\n\n" );
        $pki_instance_registry->print( "# Tomcat name :)\n" );
        $pki_instance_registry->print( "TOMCAT_PROG=\${PKI_INSTANCE_ID}\n" );
        $pki_instance_registry->print( "export TOMCAT_PROG\n\n" );
        $pki_instance_registry->print( "# if TOMCAT_USER is not set, use "
                                     . "tomcat5 like Apache HTTP server\n" );
        $pki_instance_registry->print( "if [ -z \"\$TOMCAT_USER\" ]; then\n" );
        $pki_instance_registry->print( "    TOMCAT_USER=\"\${PKI_USER}\"\n" );
        $pki_instance_registry->print( "    export TOMCAT_USER\n" );
        $pki_instance_registry->print( "fi\n\n" );
        $pki_instance_registry->print( "# if TOMCAT_GROUP is not set, use "
                                     . "tomcat5 like Apache HTTP server\n" );
        $pki_instance_registry->print( "if [ -z \"\$TOMCAT_GROUP\" ]; then\n" );
        $pki_instance_registry->print( "    TOMCAT_GROUP=\"\${PKI_GROUP}\"\n" );
        $pki_instance_registry->print( "    export TOMCAT_GROUP\n" );
        $pki_instance_registry->print( "fi\n\n" );
        $pki_instance_registry->print( "# Since the daemon function will "
                                     . "sandbox \$tomcat\n" );
        $pki_instance_registry->print( "# no environment stuff should be "
                                     . "defined here anymore.\n" );
        $pki_instance_registry->print( "# Please use the "
                                     . "\${PKI_INSTANCE_PATH}/conf/"
                                     . "tomcat5.conf\n" );
        $pki_instance_registry->print( "# file instead ; it will be read by "
                                     . "the \$tomcat script\n\n" );
        $pki_instance_registry->print( "PKI_LOCKDIR="
                                     . "\"/var/lock/$pki_flavor/"
                                     . "$subsystem_type\"\n" );
        $pki_instance_registry->print( "export PKI_LOCKDIR\n" );
        $pki_instance_registry->print( "PKI_LOCKFILE="
                                     . "\"\${PKI_LOCKDIR}/"
                                     . "\${PKI_INSTANCE_ID}.pid\"\n" );
        $pki_instance_registry->print( "export PKI_LOCKFILE\n" );
        $pki_instance_registry->print( "PKI_PIDFILE="
                                     . "\"\${PKI_INSTANCE_ID}.pid\"\n" );
        $pki_instance_registry->print( "export PKI_PIDFILE\n" );
        $pki_instance_registry->print( "pki_instance_configuration_file="
                                     . "\${PKI_INSTANCE_PATH}/conf/CS.cfg\n" );
        $pki_instance_registry->print( "export "
                                     . "pki_instance_configuration_file\n\n" );
        $pki_instance_registry->print( "RESTART_SERVER=\${PKI_INSTANCE_PATH}/"
                                     . "conf/"
                                     . "restart_server_after_configuration\n" );
        $pki_instance_registry->print( "export RESTART_SERVER\n\n" );
    } elsif( $subsystem_type eq $RA ||
             $subsystem_type eq $TPS ) {
        $pki_instance_registry->print( "# Establish PKI Variable \"Slot\" "
                                     . "Substitutions\n\n" );
        $pki_instance_registry->print( "PKI_INSTANCE_ID=$pki_instance_name\n" );
        $pki_instance_registry->print( "export PKI_INSTANCE_ID\n\n" );
        $pki_instance_registry->print( "PKI_HTTPD_CONF="
                                     . "$httpd_conf_instance_file_path\n" );
        $pki_instance_registry->print( "export PKI_HTTPD_CONF\n\n" );
        $pki_instance_registry->print( "PKI_SERVER_ROOT=$pki_instance_path\n" );
        $pki_instance_registry->print( "export PKI_SERVER_ROOT\n\n" );
        $pki_instance_registry->print( "PKI_SYSTEM_USER_LIBRARIES="
                                     . "$default_system_user_libraries\n" );
        $pki_instance_registry->print( "export PKI_SYSTEM_USER_LIBRARIES\n\n" );
        if( is_Fedora() || (is_RHEL() && (! is_RHEL4())) ) {
            $pki_instance_registry->print( "PKI_FORTITUDE_DIR=\"/usr\"\n" );
        } else {
            $pki_instance_registry->print( "PKI_FORTITUDE_DIR="
                                         . "\"/opt/fortitude\"\n" );
        }
        $pki_instance_registry->print( "export PKI_FORTITUDE_DIR\n\n" );
        $pki_instance_registry->print( "PKI_NSS_CONF="
                                     . "$nss_conf_instance_file_path\n" );
        $pki_instance_registry->print( "export PKI_NSS_CONF\n\n" );
        $pki_instance_registry->print( "PKI_SERVER_NAME=$host\n" );
        $pki_instance_registry->print( "export PKI_SERVER_NAME\n\n" );
        $pki_instance_registry->print( "PKI_GROUP=$pki_group\n" );
        $pki_instance_registry->print( "export PKI_GROUP\n\n" );
        $pki_instance_registry->print( "PKI_USER=$pki_user\n" );
        $pki_instance_registry->print( "export PKI_USER\n\n" );
        $pki_instance_registry->print( "##################"
                                     . "##################"
                                     . "##################"
                                     . "##################\n" );
        $pki_instance_registry->print( "#   This section contains "
                                     . "modified content of "
                                     . "\"/etc/sysconfig/httpd\"   #\n" );
        $pki_instance_registry->print( "##################"
                                     . "##################"
                                     . "##################"
                                     . "##################\n" );
        $pki_instance_registry->print( "# Configuration file for the "
                                     . "\${PKI_INSTANCE_ID} service.\n\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "# The default processing model (MPM) "
                                     . "is the process-based\n" );
        $pki_instance_registry->print( "# 'prefork' model.  A thread-based "
                                     . "model, 'worker', is also\n" );
        $pki_instance_registry->print( "# available, but does not work with "
                                     . "some modules (such as PHP).\n" );
        $pki_instance_registry->print( "# The service must be stopped before "
                                     . "changing this variable.\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "PKI_HTTPD="
                                     . "\${PKI_FORTITUDE_DIR}"
                                     . "/sbin/httpd.worker\n" );
        $pki_instance_registry->print( "export PKI_HTTPD\n\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "# To pass additional options (for "
                                     . "instance, -D definitions) to the\n" );
        $pki_instance_registry->print( "# httpd binary at startup, "
                                     . "set PKI_OPTIONS here.\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "PKI_OPTIONS="
                                     . "\"-f \${PKI_HTTPD_CONF}\"\n" );
        $pki_instance_registry->print( "export PKI_OPTIONS\n\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "# By default, the httpd process "
                                     . "is started in the C locale; to\n" );
        $pki_instance_registry->print( "# change the locale in which the "
                                     . "server runs, the PKI_HTTPD_LANG\n" );
        $pki_instance_registry->print( "# variable can be set.\n" );
        $pki_instance_registry->print( "#\n" );
        $pki_instance_registry->print( "PKI_HTTPD_LANG=C\n" );
        $pki_instance_registry->print( "export PKI_HTTPD_LANG\n" );
        $pki_instance_registry->print( "##################"
                                     . "##################"
                                     . "##################"
                                     . "##################\n" );
        $pki_instance_registry->print( "#                 "
                                     . "                  "
                                     . "                  "
                                     . "                 #\n" );
        $pki_instance_registry->print( "##################"
                                     . "##################"
                                     . "##################"
                                     . "##################\n\n" );
        $pki_instance_registry->print( "# This will prevent initlog from "
                                     . "swallowing up a pass-phrase prompt "
                                     . "if\n" );
        $pki_instance_registry->print( "# mod_ssl needs a pass-phrase from "
                                     . "the user.\n" );
        $pki_instance_registry->print( "PKI_INITLOG_ARGS=\"\"\n" );
        $pki_instance_registry->print( "export PKI_INITLOG_ARGS\n\n" );
        $pki_instance_registry->print( "# Set PKI_HTTPD=/usr/sbin/httpd.worker "
                                     . "in /etc/sysconfig/httpd to use a "
                                     . "server\n" );
        $pki_instance_registry->print( "# with the thread-based \"worker\" "
                                     . "MPM; BE WARNED that some modules "
                                     . "may not\n" );
        $pki_instance_registry->print( "# work correctly with a "
                                     . "thread-based MPM; notably "
                                     . "PHP will refuse to start.\n\n" );
        $pki_instance_registry->print( "# Path to the server binary and "
                                     . "short-form for messages.\n" );
        $pki_instance_registry->print( "httpd=\${PKI_HTTPD}\n" );
        $pki_instance_registry->print( "export httpd\n" );
        $pki_instance_registry->print( "prog=\${PKI_INSTANCE_ID}\n" );
        $pki_instance_registry->print( "export prog\n" );
        $pki_instance_registry->print( "PKI_LOCKDIR="
                                     . "\"/var/lock/$pki_flavor/"
                                     . "$subsystem_type\"\n" );
        $pki_instance_registry->print( "export PKI_LOCKDIR\n" );
        $pki_instance_registry->print( "PKI_LOCKFILE="
                                     . "\"\${PKI_LOCKDIR}/"
                                     . "\${PKI_INSTANCE_ID}.pid\"\n" );
        $pki_instance_registry->print( "export PKI_LOCKFILE\n" );
        $pki_instance_registry->print( "PKI_PIDFILE="
                                     . "\"\${PKI_INSTANCE_ID}.pid\"\n" );
        $pki_instance_registry->print( "export PKI_PIDFILE\n" );
        $pki_instance_registry->print( "pki_instance_configuration_file="
                                     . "\${PKI_SERVER_ROOT}/conf/CS.cfg\n" );
        $pki_instance_registry->print( "export "
                                     . "pki_instance_configuration_file\n" );
        $pki_instance_registry->print( "pki_logs_directory="
                                     . "\${PKI_SERVER_ROOT}/logs\n" );
        $pki_instance_registry->print( "export "
                                     . "pki_logs_directory\n" );
        $pki_instance_registry->print( "RESTART_SERVER=\${PKI_SERVER_ROOT}/"
                                     . "conf/"
                                     . "restart_server_after_configuration\n" );
        $pki_instance_registry->print( "export RESTART_SERVER\n" );
        $pki_instance_registry->print( "RETVAL=0\n" );
        $pki_instance_registry->print( "export RETVAL\n\n" );
        $pki_instance_registry->print( "# see if httpd is linked with the "
                                     . "openldap libraries - we need to "
                                     . "override them\n" );
        $pki_instance_registry->print( "if [ \${OS} = \"Linux\" ]; then\n" );
        $pki_instance_registry->print( "    hasopenldap=0\n\n" );
        $pki_instance_registry->print( "    /usr/bin/ldd \${httpd} 2>&1 | "
                                     . "grep libldap- > /dev/null 2>&1 && "
                                     . "hasopenldap=1\n\n" );
        $pki_instance_registry->print( "    if [ \${hasopenldap} -eq 1 ] ; "
                                     . "then\n" );
        $pki_instance_registry->print( "        LD_PRELOAD="
                                     . "\"\${PKI_SYSTEM_USER_LIBRARIES}/"
                                     . "libldap60.so\"\n" );
        $pki_instance_registry->print( "        LD_PRELOAD="
                                     . "\"\${PKI_SYSTEM_USER_LIBRARIES}/"
                                     . "libssl3.so:"
                                     . "\${LD_PRELOAD}\"\n" );
        $pki_instance_registry->print( "        export LD_PRELOAD\n" );
        $pki_instance_registry->print( "    fi\n" );
        $pki_instance_registry->print( "elif [ \${OS} = \"SunOS\" ]; then\n" );
        $pki_instance_registry->print( "    LD_PRELOAD_64="
                                     . "\"\${PKI_SYSTEM_USER_LIBRARIES}/"
                                     . "libldap60.so\"\n" );
        $pki_instance_registry->print( "    LD_PRELOAD_64="
                                     . "\"\${PKI_SYSTEM_USER_LIBRARIES}/"
                                     . "dirsec/libssl3.so:"
                                     . "\${LD_PRELOAD_64}\"\n" );
        $pki_instance_registry->print( "    export LD_PRELOAD_64\n" );
        $pki_instance_registry->print( "fi\n" );
    }

    # close and save this PKI instance's registry entry
    $pki_instance_registry->close();

    $result = give_file_to( $pki_instance_registry_entry,
                            $root_user,
                            $root_group );
    if( !$result ) {
        emit( "$pki_instance_registry_entry ownership problems!",
              "error" );
        return 0;
    }

    chmod( $default_file_permissions,
           $pki_instance_registry_entry );

    push( @installed_files,
          $pki_instance_registry_entry );

    return 1;
}

# no args
# return 1 - success, or
# return 0 - failure
sub register_pki_instance()
{
    my $result = 0;

    $result = build_pki_registry_subsystem_path();
    if( !$result ) {
        return 0;
    }

    $result = construct_pki_instance_registry();
    if( !$result ) {
        return 0;
    }

    return 1;
}

sub parse_selinux_ports()
{
    open SM, '/usr/sbin/semanage port -l |grep tcp |sed \'s/tcp/___/g\'|sed \'s/\s//g\'|';
    while (<SM>) {
         chomp($_);
         my ($type, $portstr) = split /___/, $_;
         my @ports = split /,/, $portstr;
         foreach my $port (@ports) {
            if ($port =~ /(.*)-(.*)/) {
                for (my $count = $1; $count <= $2; $count++) {
                   $selinux_ports{$count} =  $type;
                }
            } else {
                $selinux_ports{$port} = $type;
            }
         }
    }
    close(SM);
}

sub check_selinux_port()
{
    my ($setype, $seport) = @_;
    if (defined $selinux_ports{$seport}) {
        if ($selinux_ports{$seport} eq $setype) {
            return $SELINUX_PORT_DEFINED;
        } else {
            return $SELINUX_PORT_WONGLY_DEFINED;
        }
    } else {
        return $SELINUX_PORT_UNDEFINED;
    }
}

sub add_selinux_port()
{
    my($setype, $seport) = @_;
    my $status = &check_selinux_port($setype, $seport);
    if ($status == $SELINUX_PORT_UNDEFINED) {
        emit("Setting selinux context $setype for $seport\n");
        system("$semanage port -a -t $setype -p tcp $seport\n");
        if ($? != 0) {
            print STDERR "Error in setting selinux context $setype for $seport\n";
            print STDOUT "\n";
        }
    }
    elsif ($status == $SELINUX_PORT_WRONGLY_DEFINED) {
        print STDERR "Error in setting selinux context $setype for $seport\n";
        print STDOUT "\n";
    }
}

sub add_selinux_file_context()
{
   my($fcontext, $fname, $ftype) = @_;
   
   #check if fcontext has already been set
   if (`$semanage fcontext -l -n |grep $fname |grep ":$fcontext:" | wc -l` == 1) {
      #selinux context already defined
      return;
   }
   emit("Setting selinux file context for $fname\n");
   if ($ftype eq "f") {
       system("$semanage fcontext -a -t $fcontext -f -- $fname");
   } else {
       system("$semanage fcontext -a -t $fcontext $fname");
   }
   if ($? != 0) {
       print STDERR "Error in setting selinux file context $fcontext for $fname\n";
       print STDOUT ("\n");
   }
}


sub process_pki_selinux_setup()
{
    my $result = 0;
    my $setype = "pki_" . $subsystem_type;
    my $setype_p = $setype . "_port_t";
    my $default_inst_name = "pki-" . $subsystem_type;
    my $default_inst_root = "/var/lib";
    my $default_log_path = "/var/log/" . $default_instance_name;
    my $default_conf_path = "/etc/" . $default_instance_name;
    my $status = 0;

    my $conf_path;
    my $log_path;
    my $ftype;
    my $java_component = 0;

    if ($redirected_logs_path eq "") {
        $log_path = $logs_instance_path;
    }
    else {
        $log_path =$redirected_logs_path;
    }

    if ($redirected_conf_path eq "") {
        $conf_path = $conf_instance_path;
    }
    else {
        $conf_path =$redirected_conf_path;
    }

    if (($subsystem_type eq $CA) || ($subsystem_type eq $KRA) || ($subsystem_type eq $OCSP) 
        || ($subsystem_type eq $TKS)) {
        $java_component =1;
    }

    # set file contexts
    if ($java_component) {
        emit("Restorecon file context for /usr/share/java/pki\n");
        system("$restorecon -F -R /usr/share/java/pki");
    }
    emit("Restorecon file context for /usr/share/pki\n");
    system("$restorecon -F -R /usr/share/pki");

    # set file context for /usr/bin/dtomcat5-$pki_instance_name
    if ($java_component) {
        if ($pki_instance_name ne $default_inst_name ) {
            &add_selinux_file_context($setype . "_exec_t",  
                "/usr/bin/dtomcat5-$pki_instance_name", "f");
        } 
        emit("restorecon file context for /usr/bin/dtomcat5-$pki_instance_name\n");
        system("$restorecon -F -R /usr/bin/dtomcat5-$pki_instance_name");
    }
 
    # set file context for $pki_instance_root/$pki_instance_name
    if (($pki_instance_name ne $default_inst_name) || ($pki_instance_root ne $default_inst_root)) {
        &add_selinux_file_context( $setype . "_var_lib_t", 
            "\"$pki_instance_root/$pki_instance_name(/.*)?\"", "a");
    }
    emit("Restorecon file context for $pki_instance_root/$pki_instance_name\n");
    system("$restorecon -F -R $pki_instance_root/$pki_instance_name");


    if ($java_component) {
        # set file context for /var/run/$pki_instance_name.pid
        if ($pki_instance_name ne $default_inst_name ) {
            &add_selinux_file_context( $setype . "_var_run_t", 
                "/var/run/$pki_instance_name\\.pid", "f");
        }
        emit("Restorecon file context for /var/run\n");
        system("$restorecon -F -R /var/run");
    }

    # set file context for $log_path
    $log_path =~ s/\/+$//;
    if ($log_path eq "") {
        emit("Error: Cannot set selinux context $setype" . "_log_t for directory /");
    } else {
        if ($log_path ne $default_log_path) {
            &add_selinux_file_context( $setype . "_log_t", 
                "\"$log_path(/.*)?\"", "a");
        }
        emit("Restorecon file context for $log_path\n");
        system("$restorecon -F -R $log_path");
    }

    # set file context for $conf_path
    $conf_path =~ s/\/+$//;
    if ($conf_path eq "") {
        emit("Error: Cannot set selinux context $setype" . "_etc_rw_t for directory /");
    } else {
        if ($conf_path ne $default_conf_path) {
            &add_selinux_file_context( $setype . "_etc_rw_t", 
                "\"$conf_path(/.*)?\"", "a");
        } 
        emit("Restorecon $conf_path\n");
        system("$restorecon -F -R $conf_path");
    }
    
    # set file context for $conf_path/tomcat5.conf
    if ($java_component) {
        if ($conf_path ne $default_conf_path) {
            &add_selinux_file_context( $setype . "_tomcat_exec_t", 
                "$conf_path/tomcat5\\.conf", "f");
        } 
        emit("Restorecon file context for $conf_path/tomcat5.conf\n");
        system("$restorecon -F -R $conf_path/tomcat5.conf");
    }

    if (! $java_component) {
        emit("Restorecon file context for /usr/sbin/httpd.worker \n");
        system("$restorecon -F -R /usr/sbin/httpd.worker");
    }    

    # add ports
    parse_selinux_ports();
    if ($secure_port != -1) {
        &add_selinux_port($setype_p, $secure_port);
    }
    if ($non_clientauth_secure_port != -1) {
        &add_selinux_port($setype_p, $non_clientauth_secure_port);
    }
    if ($unsecure_port != -1) {
        &add_selinux_port($setype_p, $unsecure_port);
    }
    if ($tomcat_server_port != -1) {
        &add_selinux_port($setype_p, $tomcat_server_port);
    }
    if ($agent_secure_port != -1) {
        &add_selinux_port($setype_p, $agent_secure_port);
    }
    if ($ee_secure_port != -1) {
        &add_selinux_port($setype_p, $ee_secure_port);
    }
    if ($ee_secure_client_auth_port != -1) {
        &add_selinux_port($setype_p, $ee_secure_client_auth_port);
    }
    if ($admin_secure_port != -1) {
        &add_selinux_port($setype_p, $admin_secure_port);
    }
}

# no args
# return 1 - success, or
# return 0 - failure
sub install_pki_instance()
{
    my $result = 0;

    emit( "Installing PKI instance ...\n" );

    if( !directory_exists( "$pki_instance_path" ) ) {
        $result = create_directory( "$pki_instance_path" );

        push( @installed_stray_directories,
              "$pki_instance_path" );
        if( !$result ) {
            return 0;
        }
    }

    $result = process_pki_directories();
    if( !$result ) {
        return 0;
    }

    $result = process_pki_templates();
    if( !$result ) {
        return 0;
    }

    $result = process_pki_files_and_symlinks();
    if( !$result ) {
        return 0;
    }

    $result = process_pki_security_databases();
    if( !$result ) {
        return 0;
    }

    $result = process_pki_security_modules();
    if( !$result ) {
        return 0;
    }

    $result = register_pki_instance();
    if( !$result ) {
        return 0;
    }

    if (($^O eq "linux") && ( is_Fedora() || (is_RHEL() && (! is_RHEL4())))){
        $result = process_pki_selinux_setup();
        if (!result ) {
            return 0;
        }
    }

    return 1;
}


##############################################################
# PKI Instance Removal Subroutines
##############################################################

# no args
# return 1 - success, or
# return 0 - failure
sub save_cleanup_file()
{
    my $result = 0;

    my $cleanup = new FileHandle;

    my $source_file_path = $pki_instance_path
                         . "/" . $saved_cleanup_file_name;

    my $files_size = @installed_files;
    my $directories_size = @installed_stray_directories;

    if( $files_size == 0 && $installed_stray_directories == 0 ) {
        emit( "No files or directories created in save_cleanup_file!",
              "error" );
        return $result;
    }

    $cleanup->open( ">$source_file_path" ) or
    die "Could not open $source_file_path\n";

    my $buff = "";

    $cleanup->print( "$saved_file_marker\n" );

    if( $files_size ) {
        my $i = 0;

        for( $i = 0; $i < $files_size; $i++ ) {
            $cleanup->print( "$installed_files[$i]\n" );
        }
    }

    $cleanup->print( "$saved_directory_marker\n" );

    if( $directories_size ) {
        my $i = 0;

        for( $i = 0; $i < $directories_size; $i++ ) {
            $cleanup->print( "$installed_stray_directories[$i]\n" );
        }
    }

    $cleanup->close();

    return 1;
}


# no args
# no return value
sub cleanup()
{
    my $result = 0;

    print( STDOUT
           "\n\nPKI instance creation Cleanup Utility "
         . "cleaning up on error ...\n\n" );

    $result = remove_directory( "$pki_instance_path" );

    my $size = @installed_files;

    if( $size ) {
        my $i = 0;

        for( $i = 0; $i < $size; $i ++ ) {
            remove_file( $installed_files[$i] );
        }
    }

    $size = @installed_stray_directories;

    if( $size ) {
        my $i = 0;

        for( $i = 0; $i < $size; $i++ ) {
            remove_directory( $installed_stray_directories[$i] );
        }
    }

    # If empty, remove the PKI subsystem-level registry
    if( directory_exists( $pki_registry_subsystem_path ) ) {
        if( is_directory_empty( $pki_registry_subsystem_path ) ) {
            remove_directory( $pki_registry_subsystem_path );
        }
    }

    # If empty, remove the PKI-level registry
    if( directory_exists( $pki_registry_path ) ) {
        if( is_directory_empty( $pki_registry_path ) ) {
            remove_directory( $pki_registry_path );
        }
    }

    return;
}


##############################################################
# Main Program
##############################################################

# no args
# no return value
sub main()
{
    my $result = 0;
    my $parse_result = 0;
    my $command = "";

    chdir( "/tmp" );

    print( STDOUT
           "PKI instance creation Utility ...\n\n" );

    # On Linux/UNIX, insure that this script is being run as "root".
    $result = check_for_root_UID();
    if( !$result ) {
        usage();
        exit 255;
    }

    # Setup platform-dependent parameters
    setup_platform_dependent_parameters();

    $parse_result = parse_arguments();
    if( !$parse_result || $parse_result == -1 ) {
        # If it exists, close the log file
        close_logfile( $logfile );
        exit 255;
    }

    initialize_paths();

    initialize_pki_creation_values();

    if( $subsystem_type eq $CA   ||
        $subsystem_type eq $KRA  ||
        $subsystem_type eq $OCSP ||
        $subsystem_type eq $TKS ) {
        if( -e $pkicomplete ) {
            `$pkicomplete`;
        }
    }

    $result = install_pki_instance();
    if( !$result ) {
        print( STDOUT "\n" );

ASK_AGAIN:
        my $confirm  = prompt( "Error detected would you like to clean up "
                             . "$pki_instance_path (Y/N)? " );

        if( $confirm eq "Y" || $confirm eq "y" ) {
            cleanup();
        } elsif( $confirm ne "N" && $confirm ne "n" ) {
           goto ASK_AGAIN;
        }

        # If it exists, close the log file
        close_logfile( $logfile );

        exit 255;
    }

    print( STDOUT "\n" );
    print( STDOUT
           "PKI instance creation completed ...\n\n" );


    $result = save_cleanup_file();
    if( !$result ) {
        emit( "Unable to create "
            . $pki_instance_path
            . "/" . $saved_cleanup_file_name
            . "!\n",
              "error" );

        # If it exists, close the log file
        close_logfile( $logfile );

        exit 255;
    }

    # Activate this instance
    if( $^O eq "linux" ) {
        $pki_init_script_command = "/sbin/service"
                                 . " " . $pki_init_script
                                 . " " . "restart"
                                 . " " . $pki_instance_name;
    } else {
        # default case:  e. g. - ( $^O eq "solaris" )
        $pki_init_script_command = $default_init_scripts_path
                                 . "/" . $pki_init_script
                                 . " " . "restart"
                                 . " " . $pki_instance_name;
    }

    $command = "$pki_init_script_command";

    system( "$command" );

    # Notify user to check firewall settings . . .
    print( STDOUT
           "Before proceeding with the configuration, make sure \n"
           . "the firewall settings of this machine permit proper \n"
           . "access to this subsystem. \n\n");

    # EXCEPTION:  To enable a user to easily configure their PKI subsystem,
    #             this is the ONLY instance in which we print out the actual
    #             value of the the one-time random PIN, as well as store this
    #             message at the end of the initialization log.
    if( $subsystem_type eq $CA   ||
        $subsystem_type eq $KRA  ||
        $subsystem_type eq $OCSP ||
        $subsystem_type eq $TKS ) {
        if( $admin_secure_port > 0 ) {
            # Port Separation:  CA, KRA, OCSP, TKS
            print( STDOUT
                   "Please start the configuration by accessing:\n\n"
                 . "https://$host:$admin_secure_port/$subsystem_type/admin/"
                 . "console/config/login?pin=$random\n\n" );
            emit( "Configuration Wizard listening on\n"
                . "https://$host:$admin_secure_port/$subsystem_type/admin/"
                . "console/config/login?pin=$random\n",
                  "log" );
        } else {
            # Shared Ports:  CA, KRA, OCSP, TKS
            print( STDOUT
                   "Please start the configuration by accessing:\n\n"
                 . "https://$host:$secure_port/$subsystem_type/admin/"
                 . "console/config/login?pin=$random\n\n" );
            emit( "Configuration Wizard listening on\n"
                . "https://$host:$secure_port/$subsystem_type/admin/"
                . "console/config/login?pin=$random\n",
                  "log" );
        }
    } else {
        # Port Separation:  RA, TPS
        print( STDOUT
               "Please start the configuration by accessing:\n\n"
             . "https://$host:$non_clientauth_secure_port/$subsystem_type/"
             . "admin/console/config/login?pin=$random\n\n" );
        emit( "Configuration Wizard listening on\n"
            . "https://$host:$non_clientauth_secure_port/$subsystem_type/"
            . "admin/console/config/login?pin=$random\n",
              "log" );
    }

    print( STDOUT
           "After configuration, the server can be operated by the command:\n\n"
         . "    $pki_init_script_command\n\n" );
    emit( "After configuration, the server can be operated by the command:\n"
        . "$pki_init_script_command\n",
          "log" );

    # If it exists, close the log file
    close_logfile( $logfile );

    return;
}


##############################################################
# PKI Instance Creation
##############################################################

main();

exit 0;

