#! /bin/sh

# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
#
# Copyright 2005-2008 Sun Microsystems, Inc. All rights reserved. 
#
# The contents of this file are subject to the terms of the GNU General Public
# License Version 3("GPL")(the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the License at
# https://common-agent-container.dev.java.net/bootstrap/legal/license.txt or
# www/bootstrap/legal/license.txt.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# When distributing the software, include this License Header Notice in each
# file and include the License file at www/bootstrap/legal/license.txt.
#
# Sun designates this particular file as subject to the "Classpath" exception
# as provided by Sun in the GPL Version 3 section of the License file that
# accompanied this code.
#
# If applicable, add the following below the License Header, with the fields
# enclosed by brackets [] replaced by your own identifying information:
#     "Portions Copyrighted [year] [name of copyright owner]"
#

#
# solaris specific helpers
#
# - cacao_core_find_java  : find jdk installed on host
# - cacao_core_find_nss   : find nss installed on host
# - cacao_core_find_jdmk  : find jdmk installed on host
# - cacao_find_jdmk_lib_dir : find jdmk jar repository
# - cacao_is_greenline_mode  : are we running under greenline
# - cacao_is_pmf_mode        : are we running under pmf
# - cacao_get_etc_base_dir : return current etc/conf base directory
# - cacao_get_var_base_dir : return current var base directory
# - cacao_get_run_base_dir : return current run base directory
# - cacao_is_initd_service_present  : tells if the init.d service is there
# - cacao_do_smf_start      : starts the container through the smf service
# - cacao_do_smf_kill_contract_processes : kills all potentially remaining processes in the SMF contract
# - cacao_is_smf_running : checks status of SMF cacao service
# - cacao_do_smf_clean : cleans up SMF state
# - cacao_do_smf_stop       : stops the container through the smf service
# - cacao_do_smf_enable_at_boot : enable the container start at reboot through the smf service.
# - cacao_is_smf_enable_at_boot : tells if the container starts at reboot through the smf service.
# - cacao_do_smf_disable_at_boot : disable the container start at reboot through the smf service.
# - cacao_reset_smf_maintenance_state : reset the maintenance state
# - cacao_greenline_exit : greenline exit code
# - cacao_add_system_hooks : add system specific configuration and hooks
# - cacao_remove_system_hooks :remove  system specific configuration and hooks
#

# - check_platform_requirements : check that minimal requirement match the current platform

# solaris specific global variables
#
# - cacao_stopping_instance : instance name being stopped (smf case)
# - cacao_starting_instance : instance name being started (smf case)
# - cacao_enabling_instance : instance name being enabled (smf case)
# - cacao_disabling_instance : instance name being disabled (smf case)
# - cacao_save_enabled : saved cacao enabled state (smf case)
# - cacao_solaris_file_loaded : tells that solaris code is loaded, used to
#   check the call to cacao_greenline_exit in case of ctrl-c before the
#   source of the file

cacao_stopping_instance=""
cacao_starting_instance=""
cacao_enabling_instance=""
cacao_disabling_instance=""
cacao_save_enabled=""
cacao_solaris_file_loaded="true"



#------------------------------------------------------------------------------
# cacao_core_find_java
#
# DESCRIPTION :
# Set cacao_java_home to a suitable Java2 runtime.
#
# PARAMETERS :
# None.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if operation is successful
# CACAO_CR_ESRCH if we cannot find dependency
#
# OUTPUT:
# none
#------------------------------------------------------------------------------
cacao_core_find_java() {
    # Map to a number we can do a numerical comparison on.
    weWant="${CACAO_MIN_JAVA_VERSION_NUM}"

    # We start by checking the presence of a JAVA 6 binary
    jdk="SUNWj6rt"
    # No need to check the version, we KNOW this is a 1.6 release
    _basedir="`env LANG=C LC_ALL=C ${PKGPARAM} ${jdk} BASEDIR 2>/dev/null`"
    if [ $? -eq 0 ] && [ -n "${_basedir}" ]
    then
	_binary_home="`${LS} -d ${_basedir}/jdk/jdk1.6.* 2>/dev/null | ${SORT} | ${TAIL} -1`"
	if [ -x "${_binary_home}" ]
        then
	    cacao_java_home="`cacao_clean_path ${_binary_home}`"
	    return ${CACAO_CR_SUCCESS}
	fi
    fi

    # We continue by checking the presence of a JAVA 5 binary
    jdk="SUNWj5rt"
    # No need to check the version, we KNOW this is a 1.5 release
    _basedir="`env LANG=C LC_ALL=C ${PKGPARAM} ${jdk} BASEDIR 2>/dev/null`"
    if [ $? -eq 0 ] && [ -n "${_basedir}" ]
    then
	_binary_home="`${LS} -d ${_basedir}/jdk/jdk1.5.* 2>/dev/null | ${SORT} | ${TAIL} -1`"
	if [ -x "${_binary_home}" ]
        then
	    cacao_java_home="`cacao_clean_path ${_binary_home}`"
	    return ${CACAO_CR_SUCCESS}
	fi
    fi

    # Check for a suitable Java by introspecting the SUNWj3rt package
    jdk="SUNWj3rt"
    # Get version, and map to a number we can do a
    # numerical comparison on.
    version="`env LANG=C LC_ALL=C ${PKGPARAM} $jdk SUNW_PRODVERS 2>/dev/null | ${AWK} -F/ '{print $1}'`"
    if [ $? -eq 0 ] && [ -n "${version}" ]
    then
	weHave="`cacao_jdk_version_to_num $version`"
	if [ ${weHave} -ge ${weWant} ]
	then
	    _basedir="`env LANG=C LC_ALL=C ${PKGPARAM} ${jdk} BASEDIR`"
	    if [ -x "${_basedir}/j2se/bin/java" ]
            then
		    cacao_java_home="`cacao_clean_path ${_basedir}/j2se`"
		    return ${CACAO_CR_SUCCESS}
	    fi
	fi
    fi

    # Support for Solaris 10 diskless

    _basedir="${CACAO_J6RT_DEFAULT_BASEDIR}"
    if [ -n "${_basedir}" ]
    then
	_java_home="`${LS} -d ${_basedir}/jdk/jdk1.6.* 2>/dev/null | \
            ${SORT} | ${TAIL} -1`"
	if [ -x "${_java_home}" ]
        then
            # Set a valid global variable
            cacao_java_home="`cacao_clean_path ${_java_home}`"
	    return ${CACAO_CR_SUCCESS}
	fi
    fi

    _basedir="${CACAO_J5RT_DEFAULT_BASEDIR}"
    if [ -n "${_basedir}" ]
    then
	_java_home="`${LS} -d ${_basedir}/jdk/jdk1.5.* 2>/dev/null | \
            ${SORT} | ${TAIL} -1`"
	if [ -x "${_java_home}" ]
        then
            # Set a valid global variable
            cacao_java_home="`cacao_clean_path ${_java_home}`"
	    return ${CACAO_CR_SUCCESS}
	fi
    fi

    return ${CACAO_CR_ESRCH}
}

#------------------------------------------------------------------------------
# cacao_core_find_nss
#
# DESCRIPTION :
# Set cacao_nss_lib_home, cacao_nss_tools_home
#
# PARAMETERS :
# None.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if operation is successful
# CACAO_CR_ESRCH if we cannot find dependency
#
# OUTPUT:
# None.
#------------------------------------------------------------------------------
cacao_core_find_nss() {

    tmp_lib_home=""
    tmp_tools_home=""

    # Is the SUNWtls package installed ?
    ## NSS lib package found. Locate the home of libraries.
    nsslibdir=`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_NSS_LIB_PKG} BASEDIR 2>/dev/null`
    if [ $? -eq 0 ] && [ -n "${nsslibdir}" ]
	then
	if [ ! -f "${nsslibdir}/${CACAO_NSS_LIB_DIR}/${CACAO_NSS_LIB_NAME}" ]
	then
	    return ${CACAO_CR_ESRCH}
	fi
	tmp_lib_home="${nsslibdir}/${CACAO_NSS_LIB_DIR}"
    fi

    # Is the SUNWtlsu package installed ?
    ## NSS Tools package found. Find where is certutil
    nsstoolsdir=`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_NSS_TOOLS_PKG} BASEDIR 2>/dev/null`
    if [ $? -eq 0 ] && [ -n "${nsstoolsdir}" ]
    then
	if [ ! -x "${nsstoolsdir}/${CACAO_NSS_TOOLS_DIR}/${CACAO_NSS_TOOLS_NAME}" ]
	then
	    return ${CACAO_CR_ESRCH}
	fi
	tmp_tools_home="${nsstoolsdir}/${CACAO_NSS_TOOLS_DIR}"
    fi

    if [ -n "${tmp_lib_home}" ] && [ -n "${tmp_tools_home}" ]
    then
	cacao_nss_tools_home=`cacao_clean_path ${tmp_tools_home}`
	cacao_nss_lib_home=`cacao_clean_path ${tmp_lib_home}`
	return ${CACAO_CR_SUCCESS}
    fi

    # Support for Solaris 10 diskless
    _basedir="${CACAO_NSS_DEFAULT_BASEDIR}"
    if [ -n "${_basedir}" ]
    then
        if [ -z "${tmp_lib_home}" ]
        then
            tmp_lib_home="${_basedir}${CACAO_NSS_LIB_DIR}"
            if [ ! -f "${tmp_lib_home}/${CACAO_NSS_LIB_NAME}" ]
	    then
                return ${CACAO_CR_ESRCH}
            fi
        fi
        if [ -z "${tmp_tools_home}" ]
        then
            tmp_tools_home="${_basedir}${CACAO_NSS_TOOLS_DIR}"
            if [ ! -f "${tmp_tools_home}/${CACAO_NSS_TOOLS_NAME}" ]
            then
                return ${CACAO_CR_ESRCH}
            fi
        fi
    fi
    if [ -n "${tmp_lib_home}" ] && [ -n "${tmp_tools_home}" ]
    then
        # Set valid global variables
	cacao_nss_tools_home=`cacao_clean_path ${tmp_tools_home}`
	cacao_nss_lib_home=`cacao_clean_path ${tmp_lib_home}`
	return ${CACAO_CR_SUCCESS}
    else
        return ${CACAO_CR_ESRCH}
    fi
}

#------------------------------------------------------------------------------
# cacao_find_jdmk_lib_dir
#
# DESCRIPTION :
# Set cacao_jdmk_lib_dir
#
# PARAMETERS :
# jdmk home path
#
# RETURN CODE:
# CACAO_CR_SUCCESS
# CACAO_CR_ESRCH
#
# OUTPUT:
# None.
#------------------------------------------------------------------------------
cacao_find_jdmk_lib_dir() {

    _jdmk_home="$1"

    # Priority to any JDMK bundled into Solaris
    if [ -f "${_jdmk_home}/jdmkrt.jar" ]; then
        # Set a valid global variable
        cacao_jdmk_lib_dir="${_jdmk_home}"
        return ${CACAO_CR_SUCCESS}
    fi

    # Do minimum checks
    if [ -f "${_jdmk_home}/lib/jdmkrt.jar" ]; then
        cacao_jdmk_lib_dir="${_jdmk_home}/lib"
        return ${CACAO_CR_SUCCESS}
    fi

    # Not found
    return ${CACAO_CR_ESRCH}
}

#------------------------------------------------------------------------------
# cacao_core_find_jdmk
#
# DESCRIPTION :
# Set cacao_jdmk_home
#
# PARAMETERS :
# None.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if successful
# CACAO_CR_ESRCH if we cannot find dependency
#
# OUTPUT:
# None.
#------------------------------------------------------------------------------
cacao_core_find_jdmk() {

    weWant=${CACAO_MIN_JDMK_VERSION_NUM}

    # Priority to any JDMK bundled into Solaris
    _basedir="`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_JDMK_BASE_PKG} BASEDIR 2>/dev/null`"
    if [ $? -eq 0 ] && [ -n "${_basedir}" ]; then
        _jdmk_home="${_basedir}/${CACAO_JDMK_BASE_SUB_DIR}"
        if [ -f "${_jdmk_home}/jdmkrt.jar" ]; then
            # Set a valid global variable
            cacao_jdmk_home=`cacao_clean_path ${_jdmk_home}`
            return ${CACAO_CR_SUCCESS}
        fi
    fi

    # Are the SUNWjdmk-runtime and SUNWjdmk-runtime-jmx packages installed ?
    cr=0
    a_version=`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_JDMK_RT_PKG} SUNW_PRODVERS 2>/dev/null`
    cr=`expr $cr + $?`
    b_version=`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_JMX_RT_PKG} SUNW_PRODVERS 2>/dev/null`
    cr=`expr $cr + $?`


    if [ ${cr} -eq 0 ]
    then
	JDMKRT_VERSION=`cacao_jdmk_version_to_num  $a_version`
	JMXRT_VERSION=`cacao_jdmk_version_to_num $b_version`

	if [ ${JDMKRT_VERSION} -eq ${JMXRT_VERSION} ]
        then
	    if [ ${JDMKRT_VERSION} -ge ${weWant} ]
            then
		jdmkdir=`env LANG=C LC_ALL=C ${PKGPARAM} ${CACAO_JDMK_RT_PKG} BASEDIR`
		if [ -f "${jdmkdir}/${CACAO_JDMK_OPT_SUB_DIR}/${a_version}/lib/jdmkrt.jar" ]
                then
		    cacao_jdmk_home=`cacao_clean_path ${jdmkdir}/${CACAO_JDMK_OPT_SUB_DIR}/${a_version}`
		    return ${CACAO_CR_SUCCESS}
		fi
	    fi
	fi
    fi

    # Support for Solaris 10 diskless
    # Priority to any JDMK bundled into Solaris
    _basedir="${CACAO_JDMK_BASE_DEFAULT_BASEDIR}"
    if [ -n "${_basedir}" ]
    then
	_jdmk_home="${_basedir}/${CACAO_JDMK_BASE_SUB_DIR}"
        if [ -f "${_jdmk_home}/jdmkrt.jar" ]
        then
            # Set a valid global variable
            cacao_jdmk_home=`cacao_clean_path ${_jdmk_home}`
            return ${CACAO_CR_SUCCESS}
        fi
    fi
    # Optional JDMK
    _basedir="${CACAO_JDMK_OPT_DEFAULT_BASEDIR}"
    if [ -n "${_basedir}" ]
    then
	_jdmk_home="`${LS} -d ${_basedir}/${CACAO_JDMK_OPT_SUB_DIR}/* \
            2>/dev/null | ${SORT} | ${TAIL} -1`"
        if [ -n "${_jdmk_home}" ]
        then
            _version="`${BASENAME} ${_jdmk_home}`"
            _number="`cacao_jdmk_version_to_num  ${_version}`"
            if [ ${_number} -ge ${weWant} ] && [ -x "${_jdmk_home}" ]
            then
                # Set a valid global variable
                cacao_jdmk_home=`cacao_clean_path ${_jdmk_home}`
                return ${CACAO_CR_SUCCESS}
            fi
        fi
    fi

    return ${CACAO_CR_ESRCH}
}


#------------------------------------------------------------------------------
# cacao_is_pmf_mode()
#
# DESCRIPTION:
# Tells if we are on pmf mode
#
# PARAMETERS:
# None.
#
# RETURN CODE:
# CACAO_TRUE if pmf mode, CACAO_FALSE otherwise
#
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_is_pmf_mode() {

    # Catch result, avoiding echo
    pmfd_pid=`cacao_get_process_pid ${PMF_DAEMON_NAME}`
    if [ ${?} -eq ${CACAO_CR_SUCCESS} ]
    then
        # PMF Deamon is running
        if [ -f ${CACAO_PMF_LOCK} ]
	then
            # RPC created a lock for PMF daemon
            ${RPCINFO} -t ${cacao_host} ${CACAO_RPC_PROGNUM} ${CACAO_RPC_VERSNUM}  >/dev/null 2>&1
            if [ $? -eq 0 ]
            then
                # Flag to indicate that PMF is available
                return ${CACAO_TRUE}
            fi
        fi
     fi
     return ${CACAO_FALSE}
}


#------------------------------------------------------------------------------
# cacao_is_greenline_mode()
#
# DESCRIPTION:
# Tells if we are on greenline mode
# calling smf_present helper function defined inside SMF_HELPER_FILE
# PARAMETERS:
# None.
#
# RETURN CODE:
# CACAO_TRUE
# CACAO_FALSE
#
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_is_greenline_mode() {

    if [ -n "${cacao_current_id}" ] && [ ${cacao_current_id} -ne 0 ]
    then
	return ${CACAO_FALSE}
    fi

    if [ -f "${SMF_HELPER_FILE}" ]
    then
        . "${SMF_HELPER_FILE}"
        smf_present
        if [ $? -eq 0 ]
	then
	    return ${CACAO_TRUE}
        else
            return ${CACAO_FALSE}
	fi
    else
	return ${CACAO_FALSE}
    fi

}

#------------------------------------------------------------------------------
# cacao_is_initd_service_present
#
# DESCRIPTION:
# Tells if the initd cacao file is there
#
# PARAMETERS:
# None.
#
# RETURN CODE:
# CACAO_TRUE
# CACAO_FALSE
#
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_is_initd_service_present() {
    if [ -f /etc/init.d/"${cacao_unique_name}" ]
    then
        return ${CACAO_TRUE}
    else
        return ${CACAO_FALSE}
    fi
}

#------------------------------------------------------------------------------
# cacao_do_smf_start
#
# DESCRIPTION :
# Start the container through the smf service.
#
# PARAMETERS :
# none.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_start() {

    # Check if Cacao is running (should not be)
    # Could be smf test and no rely on pid
    cacao_is_running
    is_running=$?
    if [ ${is_running} -eq ${CACAO_CR_ERROR} ]
    then
        return ${CACAO_CR_ESRCH}
    fi

    if [ ${is_running} -eq ${CACAO_TRUE} ]
    then
        pid=`cacao_get_pid`
        # Only one instance of Cacao allowed
        if [ ${pid} -eq 0 ]
        then
            cacao_print_error_message "${CACAO_MSG_ERROR_ALREADY_RUNNING}" \
		"${cacao_main_action}"
        else
            cacao_print_error_message "${CACAO_MSG_ERROR_ALREADY_RUNNING2}" \
		"${cacao_main_action}" "${pid}"
        fi
        return ${CACAO_CR_EEXIST}
    fi

    full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_main_instance}"
    #in case if previously in maintenance state
    cacao_reset_smf_maintenance_state "${cacao_main_instance}"
    if [ ${?} -ne 0 ]
    then
        cacao_print_error_message "${CACAO_MSG_ERROR_SMF_STARTING}" "${full_service_name}"
        return ${CACAO_CR_ERROR}
    fi

    #for ctrl-c stop in case
    cacao_starting_instance="${cacao_main_instance}"
    ${SVCADM} enable -st "${full_service_name}" >/dev/null 2>&1
    if [ ${?} -ne 0 ]
    then
        cacao_starting_instance=""
        cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_STARTING}" "${full_service_name}"
        return ${CACAO_CR_ERROR}
    fi
    cacao_starting_instance=""
    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_do_smf_kill_contract_processes
#
# DESCRIPTION :
# Kills all potentially remaining processes in the SMF contract
#
# PARAMETERS :
# service name (aka SMF fmri)
# signal (may be empty)
#
# RETURN CODE:
# none
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_kill_contract_processes() {

    if [ -z "$1" ]; then
        return ${CACAO_CR_ERROR}
    fi

    service_name=$1

    if [ -z "$2" ]; then
        signal_to_send=-2
        if [ ${cacao_force_mode} -eq ${CACAO_TRUE} ]; then
        signal_to_send=-9
        fi
    else
        signal_to_send="$2"
    fi

    # Kill all subprocesses attached to same contract

    # Get contract id from SMF FMRI
    ctid=`${SVCPROP} -p restarter/contract ${service_name}`
    # if restarter not completed ctid will not be null kill all remaining bits
    if [ ${?} -eq 0 ] && [ -n "${ctid}" ]
    then

	# Get cacao main pid
	lcacao_pid=`cacao_get_pid`
	# Get associated PID list (none gets translated to empty list)
	pidlist=`env LANG=C LC_ALL=C ${CTSTAT} -av -i $ctid 2>/dev/null | ${GREP} 'member processes:' | ${SED} -e 's/^.*member processes: *//' -e 's/none//'`
	for lpid in ${pidlist}; do
	    if [ $lpid -ne $lcacao_pid ]; then
		cacao_print_syslog_notice_message "Killing ${lpid} with signal ${signal_to_send}"
		${KILL} ${signal_to_send} ${lpid} >/dev/null 2>&1
		kill_stat=$?
		if [ ${kill_stat} -ne 0 ]; then
		    cacao_print_syslog_notice_message "Error killing ${lpid} with signal ${signal_to_send}: ${kill_stat}"
		    cacao_print_error_message "Error killing ${lpid} with signal ${signal_to_send}: ${kill_stat}"
		fi
	    fi
	done
    fi
    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_is_smf_running
#
# DESCRIPTION :
# Checks status of SMF service
#
# PARAMETERS :
# service name (aka SMF fmri)
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_is_smf_running() {

    if [ -z "$1" ]; then
        if [ -z "${CACAO_SMF_SVC_NAME_PREFIX}" ] || [ -z "${cacao_unique_name}" ] || [ -z "${cacao_main_instance}" ]; then
	    return ${CACAO_CR_ERROR}
	fi
	service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_main_instance}"
    else
        service_name=$1
    fi

    smf_state=`env LANG=C LC_ALL=C ${SVCPROP} -p restarter/state ${service_name} 2>/dev/null`
    if [ $? -ne 0 ]; then
        return ${CACAO_CR_ERROR}
    fi
    echo ${smf_state}
    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_do_smf_clean
#
# DESCRIPTION :
# Cleans up state of SMF service
#
# PARAMETERS :
# service name (aka SMF fmri)
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_clean() {

    if [ -z "$1" ]; then
        return ${CACAO_CR_ERROR}
    fi

    service_name=$1
    smf_state=`cacao_is_smf_running ${service_name}`
    if [ $? -ne ${CACAO_CR_SUCCESS} ]; then
        return ${CACAO_CR_ERROR}
    fi
    if [ "${smf_state}" = ${CACAO_SMF_ONLINE_STATE} ]; then
	cacao_print_syslog_notice_message "${CACAO_MSG_ERROR_SMF_KILL} ${CACAO_MSG_ERROR_SMF_REMAINING}"
	cacao_do_smf_kill_contract_processes "${service_name}"
    fi
    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_do_smf_stop
#
# DESCRIPTION :
# Stop the container through the smf service.
#
# PARAMETERS :
# none.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_stop() {

    service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_main_instance}"

    #cacao must be running
    cacao_is_running
    is_running=$?
    if [ ${is_running} -eq ${CACAO_CR_ERROR} ]
    then
	cacao_do_smf_clean "${service_name}"
        return $?
    fi
    #in this case there is no error
    if [ ${is_running} -eq ${CACAO_FALSE} ]
    then
	cacao_do_smf_clean "${service_name}"
        return $?
    fi

    #in case if previously in maintenance state
    cacao_reset_smf_maintenance_state "${cacao_main_instance}"
    if [ ${?} -ne 0 ]
    then
        cacao_print_error_message "${CACAO_MSG_ERROR_SMF_STOPPING}" "${service_name}"
        return ${CACAO_CR_ERROR}
    fi

    # Forced stop
    if [ ${cacao_force_mode} -eq ${CACAO_TRUE} ]
    then
        #for latter cleanup in case
        cacao_stopping_instance="${cacao_main_instance}"

        #create property group stop and property exec

        ${SVCCFG} -s ${service_name} addpg stop method  >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi
        ${SVCCFG} -s ${service_name} setprop stop/exec = astring: \"${cacao_tools_dir}/cacao_smf stop -f %i\"  >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi
        #refresh the instance to make the change active
        ${SVCADM} refresh ${service_name}  >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi
        #call stop
        ${SVCADM} disable -st ${service_name} >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_STOPPING}" "${service_name}"
        fi
        #restore previous state
        ${SVCCFG} -s ${service_name} delpg stop  >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi
        #refresh the instance to make the change active
        ${SVCADM} refresh ${service_name} >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi

	cacao_do_smf_kill_contract_processes "${service_name}"

        # we are sure here that the stop method is cleaned (rollback at exit if
        # an error occurs before)
        cacao_stopping_instance=""
        #kill cacao process if smf has no trace of it (daemon process that was in maintenance state)
        cacao_force_stop
        return ${?}
    else
        ${SVCADM} disable -st "${service_name}" >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_STOPPING}" "${service_name}"
            return ${CACAO_CR_ERROR}
         else
            #case of gracefull stop that had problems, return code is 0
            #but there is a message to print
            if [ -s "${cacao_error_file}" ]
            then
                cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_STOPPING}" "${service_name}"
            fi
        fi
    fi

    return ${CACAO_CR_SUCCESS}
}


#------------------------------------------------------------------------------
# cacao_smf_kill_remaining_processes
#
# DESCRIPTION :
# Kills all potentially remaining processes in the SMF contract
#
# PARAMETERS :
# none
#
# RETURN CODE:
# none
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_smf_kill_remaining_processes() {
    service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_main_instance}"
    cacao_do_smf_kill_contract_processes "${service_name}" "-9"
    return ${?}
}

#------------------------------------------------------------------------------
# cacao_is_smf_enable_at_boot
#
# DESCRIPTION:
# Tells if the container start or not at reboot through the smf service.
#
# PARAMETERS:
# $1 the value of the enabled property
#
# RETURN CODE:
# CACAO_TRUE
# CACAO_FALSE
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# an error message if we can't retrieve smf service status.
#
#------------------------------------------------------------------------------
cacao_is_smf_enable_at_boot() {

    service_name=${CACAO_SMF_SVC_SERVICE_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"

    # Remove the SMF svccfg command error (but keep the cacao one)
    cacao_is_smf_enabled=`${SVCPROP} -c -p general/enabled "${service_name}" 2>/dev/null`
    if [ ${?} -ne 0 ]
    then
	# Distinguish between "real" error and dissync between property and SMF state
	if [ -n "$1" ]; then
	    cacao_print_error_message "${CACAO_MSG_ERROR_SMF_ENABLE_STATUS}" "${service_name}"
	fi
        return ${CACAO_CR_ERROR}
    fi

    if [ "${cacao_is_smf_enabled}" = "${CACAO_SMF_ENABLE_TRUE_VALUE}" ]
    then
        return ${CACAO_TRUE}
    else
        return ${CACAO_FALSE}
    fi
}

#------------------------------------------------------------------------------
# cacao_do_smf_enable_at_boot
#
# DESCRIPTION :
# Enable the container start at reboot through the smf service.
# Logic implementation function.
#
# PARAMETERS :
# none.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_enable_at_boot() {

    full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"
    service_name=${CACAO_SMF_SVC_SERVICE_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"

    cacao_save_enabled=`cacao_get_property "${CACAO_ENABLE_KEY}"`

    cacao_do_enable_at_boot
    if [ ${?} -ne ${CACAO_CR_SUCCESS} ]
    then
        return ${CACAO_CR_ERROR}
    fi

    cacao_enabling_instance="${instance_name}"

    cacao_do_smf_enable_at_boot_internal "${cacao_main_instance}"
    if [ ${?} -ne ${CACAO_CR_SUCCESS} ]
    then
        cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_ENABLING}" "${full_service_name}"
	cacao_set_property "${CACAO_ENABLE_KEY}" $cacao_save_enabled
        return ${CACAO_CR_ERROR}
    fi

    cacao_enabling_instance=""

    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_do_smf_enable_at_boot_internal
#
# DESCRIPTION :
# Enable the container start at reboot through the smf service.
# Logic implementation function.
#
# PARAMETERS :
# $1 the instance name
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_enable_at_boot_internal() {
    instance_name=${1}
    full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"
    service_name=${CACAO_SMF_SVC_SERVICE_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"

    #in case if previously in maintenance state
    cacao_reset_smf_maintenance_state "${instance_name}"
    if [ ${?} -ne 0 ]
    then
        return ${CACAO_CR_ERROR}
    fi

    # Workaround for delayed enable for svcadm (see 6198442)
    smf_state=`${SVCS} -Ho STA "${service_name}" 2>/dev/null`
    if [ ${?} -ne 0 ]; then
	return ${CACAO_CR_ERROR}
    fi
    if [ "$smf_state" = "DIS" -o "$smf_state" = "UN" ]; then
        ${SVCADM} disable -st "${full_service_name}" >/dev/null 2>&1
        if [ ${?} -ne 0 ]; then
            return ${CACAO_CR_ERROR}
        fi
    elif [ "$smf_state" = "ON" ]; then
	${SVCADM} enable -st "${full_service_name}" >/dev/null 2>&1
	if [ ${?} -ne 0 ]; then
	    return ${CACAO_CR_ERROR}
	fi
    else
	return ${CACAO_CR_ERROR}
    fi

    ${SVCCFG} -s "${service_name}" "setprop general/enabled = true"
    if [ ${?} -ne 0 ]; then
        return ${CACAO_CR_ERROR}
    fi

    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_do_smf_disable_at_boot
#
# DESCRIPTION :
# Disable the container start at reboot through the smf service.
# Logic implementation function.
#
# PARAMETERS :
# $1 the instance name
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_disable_at_boot() {

    cacao_save_enabled=`cacao_get_property "${CACAO_ENABLE_KEY}"`

    cacao_do_disable_at_boot
    if [ ${?} -ne ${CACAO_CR_SUCCESS} ]
    then
        return ${CACAO_CR_ERROR}
    fi

    cacao_disabling_instance="${instance_name}"

    cacao_do_smf_disable_at_boot_internal "${cacao_main_instance}"
    if [ ${?} -ne ${CACAO_CR_SUCCESS} ]
    then
        cacao_print_smf_error_message "${CACAO_MSG_ERROR_SMF_DISABLING}" "${full_service_name}"
        return ${CACAO_CR_ERROR}
    fi

    cacao_disabling_instance=""

    return ${CACAO_CR_SUCCESS}
}


#------------------------------------------------------------------------------
# cacao_do_smf_disable_at_boot_internal
#
# DESCRIPTION :
# Disable the container start at reboot through the smf service.
# Logic implementation function.
#
# PARAMETERS :
# none.
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_do_smf_disable_at_boot_internal() {

    instance_name=${1}
    full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"
    service_name=${CACAO_SMF_SVC_SERVICE_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"

    #in case if previously in maintenance state
    cacao_reset_smf_maintenance_state "${instance_name}"
    if [ ${?} -ne 0 ]
    then
        return ${CACAO_CR_ERROR}
    fi

    # Workaround for delayed enable for svcadm (see 6198442)
    smf_state=`${SVCS} -Ho STA "${service_name}" 2>/dev/null`
    if [ ${?} -ne 0 ]; then
	return ${CACAO_CR_ERROR}
    fi
    ${SVCS} -l "${service_name}" | ${GREP} "^enabled.*true" >/dev/null 2>&1
    if [ ${?} -eq 0 ]
    then
        ${SVCADM} enable -t "${full_service_name}" >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            return ${CACAO_CR_ERROR}
        fi
    else
       ${SVCADM} disable -t "${full_service_name}" >/dev/null 2>&1
       if [ ${?} -ne 0 ]
       then
            return ${CACAO_CR_ERROR}
        fi
    fi

    ${SVCCFG} -s "${service_name}" "setprop general/enabled = false"
    if [ ${?} -ne 0 ]
    then
        return ${CACAO_CR_ERROR}
    fi

    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_reset_smf_maintenance_state
#
# DESCRIPTION :
# In case the state of the service is in maintenance state put
# it in disabled state so as next smf commands (for enabling, stopping
# starting, disabling) can work.
#
# PARAMETERS :
# $1 the instance name
#
# RETURN CODE:
# CACAO_CR_SUCCESS if the operation is successfull
# CACAO_CR_ERROR if there is an error when executing the command
#
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_reset_smf_maintenance_state() {
    instance_name=$1
    full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"
    state=`${SVCS} -Ho STA "${full_service_name}" 2>/dev/null`
    if [ ${?} -ne 0 ]
    then
        cacao_print_error_message "${CACAO_MSG_ERROR_SMF_RESET_MAINTENANCE}" "${full_service_name}"
        return ${CACAO_CR_ERROR}
    fi
    #case state in maintenance mode
    if [ ${state} = "MNT" ]
    then
        #disable the service for the instance
        #will return a 3 error code but will work
        #this is the only way to do a kind of clear of the
        #maintenance state without starting the service
        ${SVCADM} disable -st "${full_service_name}" >/dev/null 2>&1
        if  [ ${?} -ne 3 ] && [ ${?} -ne 0 ]
        then
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_RESET_MAINTENANCE}" "${full_service_name}"
            return ${CACAO_CR_ERROR}
        fi
    fi
    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# cacao_print_smf_error_message
#
# DESCRIPTION :
# Print smf message according to the locale in stderr
# Same as print error message but also print the link to smf log
# To be used after an smf call error
#
# PARAMETERS :
# $1 : the default message.
# $[2-n] : Other parameters are parameter for the message.
#
# RETURN CODE:
# none.
#
# OUTPUT:
# nothing.
#------------------------------------------------------------------------------
cacao_print_smf_error_message() {
    if [ -s "${cacao_error_file}" ]
    then
        #if there is error comming from the cacaoadm smf call
        #then print it
        ${CAT} "${cacao_error_file}" >&2
        ${RM} -f ${cacao_error_file} >/dev/null 2>&1
    else
        #the error is purely smf
        message="$1"
        shift
        parameters="$*"
        cacao_print_error_message "${message}" "${parameters}"
        full_service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${instance_name}"
        log_file=`${SVCS} -l "${full_service_name}" | ${GREP} .log\$ | ${CUT} -f7 -d' '`
        if [ -n "${log_file}" ]
        then
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_LOG}" "${log_file}"
        fi
    fi
}

#------------------------------------------------------------------------------
# cacao_greenline_exit
#
# DESCRIPTION :
# rollback of stop, enable, disable smf call in case of error for these calls
#
# PARAMETERS :
# None
#
# RETURN CODE:
# none.
#
# OUTPUT:
# nothing.
#------------------------------------------------------------------------------
cacao_greenline_exit() {

    if [ -n "${cacao_starting_instance}" ]
    then
        service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_starting_instance}"
        #stop the running instance (crtl-c case) - no synchro here !
        ${SVCADM} disable -t ${service_name} >/dev/null 2>&1
         if [ ${?} -ne 0 ]
        then
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_STOPPING}" "${service_name}"
        fi
    fi

    if [ -n "${cacao_stopping_instance}" ]
    then
        service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_stopping_instance}"
        # no test on error code here since we are not sure if the property group
        # has been setted before (so delpg may return an error)
        ${SVCCFG} -s ${service_name} delpg stop  >/dev/null 2>&1
        #refresh the instance to make the change active
        ${SVCADM} refresh ${service_name} >/dev/null 2>&1
        if [ ${?} -ne 0 ]
        then
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_ROLLBACK}" stop "${service_name}"
        fi
    fi

    if [ -n "${cacao_enabling_instance}" ]
    then
        cacao_set_property "${CACAO_ENABLE_KEY}" "${cacao_save_enabled}"
        if [ ${?} -ne 0 ]
        then
            service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_enabling_instance}"
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_ROLLBACK}" enable "${service_name}"
        fi
    fi

    if [ -n "${cacao_disabling_instance}" ]
    then
        cacao_set_property "${CACAO_ENABLE_KEY}" "${cacao_save_enabled}"
        if [ ${?} -ne 0 ]
        then
            service_name=${CACAO_SMF_SVC_NAME_PREFIX}"${cacao_unique_name}":"${cacao_disabling_instance}"
            cacao_print_error_message "${CACAO_MSG_ERROR_SMF_ROLLBACK}" disable "${service_name}"
        fi
    fi

    #clean the error message if not already done
    if [ -f "${cacao_error_file}" ] && [ "${cacao_print_error_in_file}" = "${CACAO_FALSE_VALUE}" ]
    then
        ${RM} -f ${cacao_error_file} >/dev/null 2>&1
	if [ $? -ne 0 ]
	then
	    cacao_print_error_message "${CACAO_MSG_ERROR_FILE_RM}" "${cacao_error_file}"
	fi
    fi

}


#------------------------------------------------------------------------------
# cacao_get_etc_base_dir
#
# DESCRIPTION :
# return current etc/conf base dir
# on solaris etc base = the rt base
# PARAMETERS :
# None.
# NOTICE:
# cacao_rt_base_dir must be well known
# RETURN CODE:
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_get_etc_base_dir () {
    ${ECHO}  "${cacao_rt_base_dir}"
}

#------------------------------------------------------------------------------
# cacao_get_var_base_dir
#
# DESCRIPTION :
# return current var base dir
# on solaris var base = the rt base
# PARAMETERS :
# None.
# NOTICE:
# cacao_rt_base_dir must be well known
# RETURN CODE:
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_get_var_base_dir () {
    ${ECHO}  "${cacao_rt_base_dir}"
}

#------------------------------------------------------------------------------
# cacao_get_run_base_dir
#
# DESCRIPTION :
# return current run base dir
# on solaris run base = the rt base
# PARAMETERS :
# None.
# NOTICE:
# cacao_rt_base_dir must be well known
# RETURN CODE:
# OUTPUT:
#
#------------------------------------------------------------------------------
cacao_get_run_base_dir () {
    ${ECHO}  "${cacao_rt_base_dir}"
}
#------------------------------------------------------------------------------
# cacao_add_system_hooks
#
# DESCRIPTION :
#  add system specific configuration and hooks
#  for now add script to sysidconfig(1M)
#
# PARAMETERS :
# None.
# NOTICE:
# 
# RETURN CODE:
# 
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_add_system_hooks () {
    
    #nothing is possible is not-root
    if [ -n "${cacao_current_id}" ] && [ ${cacao_current_id} -ne 0 ]
    then
	return ${CACAO_CR_SUCCESS}
    fi
    
    sysidtool_script="${cacao_private_bin_dir}/sys-unconfig-cacao-instances"

    #
    # (6788529 : cacaoadm initialisation may fail due to user wrong package usage)
    # When users do not follow uninstall procedures. the sysidconfig script 
    # may remain registered o the system. sysidconfig(1M) will raise an error if we
    # try to register the script twice.
    # In order to workaround this: we first check if the scripts is already registered
    # 
    # avoid being disturbed by grep options and behavior
    # we want to match only exact string : use awk

    ${SYSIDCONFIG} -l 2>/dev/null | ${AWK} -v pattern=${sysidtool_script} ' $1 == pattern {exit 1} '
    if [ $? -eq 1 ]
    then
       #should not be the case but script is already registered
       #stop here avoiding error
       return ${CACAO_CR_SUCCESS}
    fi

    if [ ! -x "${sysidtool_script}" ]
    then
	cacao_print_error_message  "${CACAO_MSG_ERROR_FILE_NOT_FOUND}" "${sysidtool_script}"
	return ${CACAO_CR_ERROR}
    fi
    
    
    ${SYSIDCONFIG} -a ${sysidtool_script} 2>/dev/null
    if [ $? -ne 0 ]
    then
	cacao_print_error_message  "${CACAO_MSG_ERROR_SYSIDCONFIG_REGISTRATION}"
	return ${CACAO_CR_ERROR}
    fi


    return ${CACAO_CR_SUCCESS}
}
#------------------------------------------------------------------------------
# cacao_remove_system_hooks
#
# DESCRIPTION :
#  remove system specific configuration and hooks
#  for now remove script from sysidconfig(1M)
#
# PARAMETERS :
# None.
# NOTICE:
# 
# RETURN CODE:
# 
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
cacao_remove_system_hooks () {
    #nothing is possible is not-root
    if [ -n "${cacao_current_id}" ] && [ ${cacao_current_id} -ne 0 ]
    then
	return ${CACAO_CR_SUCCESS}
    fi
    
    sysidtool_script="${cacao_private_bin_dir}/sys-unconfig-cacao-instances"

    ${SYSIDCONFIG} -l 2>/dev/null | ${GREP} ${sysidtool_script} >/dev/null 2>&1
    if [ $? -ne 0 ]
    then
	#sys-unconfig-cacao-instances not register nothing to do
	return ${CACAO_CR_SUCCESS}
    fi

    ${SYSIDCONFIG} -r ${sysidtool_script} 2>/dev/null
    if [ $? -ne 0 ]
    then
	cacao_print_error_message  "${CACAO_MSG_ERROR_SYSIDCONFIG_UNREGISTRATION}"
	return ${CACAO_CR_ERROR}
    fi


    return ${CACAO_CR_SUCCESS}
}

#------------------------------------------------------------------------------
# check_platform_requirements
#
# DESCRIPTION :
#  check that minimal requirement match the current platform
#
# PARAMETERS :
# None.
# NOTICE:
# 
# RETURN CODE:
# 
# OUTPUT:
# none
#
#------------------------------------------------------------------------------
check_platform_requirements() {
 
    # no longer usefull
    return ${CACAO_CR_SUCCESS}
}
