#!/bin/sh
#
# ident "@(#)smcwebserver	1.51 03/01/25 SMI"
#
# Copyright (c) 2002 by Sun Microsystems, Inc.
# All rights reserved.
#
 
# Start/Stop Script for the Sun Management Center Web Console Server
#

PRODUCT_NAME="Sun Management Center"
PIDFILE=/var/run/smcwebserver.pid
SERVER_STARTED_FILE=/var/tmp/webconsole.tmp
CONFIG_FILE=/etc/default/webconsole
VERSION="$PRODUCT_NAME Web Console Version 1.0"

# Save CWD so can get back to it in face of cd's
SAVECWD=`pwd`


########################################################
#
# Function to resolve a link to it's target.
#
########################################################
resolve_link() {

    prg=$1

    if [ -h "${prg}" ]; then

	# Must cd to where the symbolic link is located as a starting point
	# to follow the link.
	cd `dirname ${prg}`

	# Resolve link to conclusion
	while [ -h "${prg}" ]
	do
	    prg=`ls -al ${prg} | awk '{print $NF}'`
	    cd `dirname ${prg}`
	done

	# Resolve to full path, in case it's relative.
	prg=`pwd`/`basename ${prg}`
    fi

    echo $prg

} # resolve_link


########################################################
#
# Function to try to find a suitable Java2 runtime
#
########################################################
findJava() {

    JAVA_LOC="${JAVA_HOME:+${JAVA_HOME}/bin/java} `/bin/ksh whence java` /usr/j2se/bin/java"
    JAVA_HOME=""
    for i in ${JAVA_LOC}
    do
	prog=`resolve_link ${i}`
	if [ -x ${prog} ]; then
	    version=`${i} -version 2>&1 | head -1`

	    case ${version} in
		"java version \"1.0"*)
		    continue ;;
		"java version \"1.1"*)
		    continue ;;
		"java version \"1.2"*)
		    continue ;;
		"java version \"1.3"*)
		    continue ;;
		*)
		    JAVA_HOME=`dirname \`dirname ${prog}\``
		    export JAVA_HOME
		    break ;;
	    esac
	fi
    done

    # It is possible we didn't find one if it was installed in a non-default
    # location and the user neglected to set JAVA_HOME or include it along
    # PATH.  In this case, we try to derive it by querying the pkg database.
    #
    if [ ! -n "${JAVA_HOME}" ]; then
	j3rtpkg=`env LANG=C LC_ALL=C pkginfo | grep "J2SDK" | grep "1.4" \
	    | grep -i runtime | awk '{print $2}' | sort | head -1`
	if [ -n "${j3rtpkg}" ]; then
	    j2basedir=`env LANG=C LC_ALL=C pkginfo -l ${j3rtpkg} \
		| grep BASEDIR | awk '{print $2}'`
	    JAVA_HOME=${j2basedir}/j2se
	    export JAVA_HOME
	fi
    fi

    if [ ! -n "${JAVA_HOME}" ]; then
	echo "No suitable Java runtime found in any of the following directories:"
	echo "        \c"
	for i in $JAVA_LOC; do echo "${i} \c"; done; echo
	echo "Please set the JAVA_HOME environment variable to point to a Java 2"
	echo "installation and run $0 again."
	exit 1
    fi

    JAVA=${JAVA_HOME}/bin/java

} # findJava


########################################################
#
# Function to set the system classpath
#
########################################################
setClassPath() {

    # Tomcat
    CP="${CATALINA_HOME}/bin/bootstrap.jar"

    # Java
    if [ -f "${JAVA_HOME}/lib/tools.jar" ] ; then
	CP=${CP}:"${JAVA_HOME}/lib/tools.jar"
    fi
    if [ -f "${JAVA_HOME}/jre/lib/jsse.jar" ] ; then
	CP=${CP}:"${JAVA_HOME}/jre/lib/jsse.jar"
    fi

} # setClassPath


########################################################
#
# Output runtime parameters to log
#
########################################################
logRuntime() {

    echo "JAVA_HOME=${JAVA_HOME}" >> ${LOG_FILE}
    echo "CLASSPATH=${CP}" >> ${LOG_FILE}
    echo "CATALINA_BASE=${CATALINA_BASE}" >> ${LOG_FILE}
    echo "CATALINA_HOME=${CATALINA_HOME}" >> ${LOG_FILE}
    echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> ${LOG_FILE}

} # logRuntime


########################################################
#
# Wait for a specified file or directory to come into existence.
# In the face of Murphy's Law, apply a timeout in case 
# the file or directory isn't created.
#
# $1 = full path of file or directory to wait for
# $2 = timeout (seconds)
# $3 = type, either -d for directory or -f for file
# $4 = 1 to delete the file or directory after detection, 
#      0 to not delete it
#
########################################################
waitOnFile() {

    theFile=$1
    timeout=$2
    type=$3
    purge=$4

    t=0
    while [ $t -lt $timeout ] ; do
	sleep 1
	if [ "${type}" "${theFile}" ]; then
	    if [ $purge -eq 1 ]; then
		rm -rf ${theFile}
	    fi
	    break;
	fi
	t=`(expr $t + 1)`
    done

} # waitOnFile


########################################################
#
# Ovverwrite the /etc/default/webconsole file with an ENABLE="yes/no"
# entry
#
# $1 = yes/no
# $2 = the default config file : /etc/default/webconsole
#
########################################################
writeText() {

        arg=$1

        cat > ${CONFIG_FILE} <<EOF
#Do not edit this file.
#Used to configure default settings for the webconsole.
#Set ENABLE to "yes" to start console webserver during boot time.
#Setting ENABLE to "no" will NOT start console webserver during boot time.
#Setting ENABLE to any other value will not start the webserver but
#log a config error message in syslog.
ENABLE=${arg}
EOF
}


###################################################################
#
# Check to see if there are any registered management applications and
# continue with the console startup only if applications are registered
#
###################################################################

checkForApps() {

    CONSOLE="com.sun.web.console_1.0"
    TAGS="com.sun.web.ui_1.0"
    TMP_PLUGIN="/tmp/plugin_file"

    # locate the registered_plugins file

    WEBBASES="`cd \`dirname $0\`/..; pwd` /usr/sadm"
    for w in ${WEBBASES}
    do
        PLUGINS=${w}/lib/webconsole/registered_plugins
        if [ -f "${PLUGINS}" ]; then
            break
        fi
        PLUGINS=""
    done

    # if file found look for registered apps inside it
    # exclude the console and tags from the list of 
    # registered apps as these are not really apps. 
    # otherwise report error and exit

    if [ -f "${PLUGINS}" ]; then
        cat $PLUGINS | nawk 'BEGIN {
            CONSOLE_OR_TAG="false"
        }
        /'$CONSOLE'/                  {CONSOLE_OR_TAG="true"}
        /'$TAGS'/                     {CONSOLE_OR_TAG="true"}

        # main functionality
        {
                if (CONSOLE_OR_TAG == "false")
                {
                        print
                }
		else 
		{
			CONSOLE_OR_TAG="false"
		}
        }
        END {}' > $TMP_PLUGIN.$$

        TMP=`cat $TMP_PLUGIN.$$ \
            | sed -e 's/    / /g' -e 's/^ //g' -e '/^#/d' -e 's/ //g'`

	rm -f $TMP_PLUGIN.$$

        if [ "$TMP" = "" ]; then
	    echo "Server not started! No management applications registered."
	    exit 0
        fi
    else
	echo "Server not started! Cannot find registered plugins file"
        exit 1
    fi

}

###################################################################
# Find and execute the script that contains all the "smloginmodule"
# commands that were created during pkgadd by the various packages
# that delivered JAAS LoginModules
###################################################################
updateLoginModules() {

#
# Locate script file and execute it.  Try the most obvious
# locations before giving up.
#
WEBBASES="`cd \`dirname $0\`/..; pwd` /usr/sadm"
for w in ${WEBBASES}
do
    LOGINSCRIPT=${w}/lib/webconsole/lib/.consolelogin
    if [ -f "${LOGINSCRIPT}" ]; then
        break
    fi
    LOGINSCRIPT=""
done

if [ -f "${LOGINSCRIPT}" ]; then
    . ${LOGINSCRIPT}
fi

}

#######################################################################
# Return the unique id that represents the server machine one which the
# webserver will be running. This will be used to assign uniqueness to
# the certificate being generated. The procudure will be as follows:
#
#   - try /usr/bin/hostname, if the hostname contains a "." it is most
#     probably the FQDN, if we get a reply from ping, use it.
#   - if DNS configured use nslookup;  if we get a reply from ping, use it.
#   - try `/bin/hostname`/`/bin/domainname`; if we get a reply from ping,
#     use it.
#   - when all else fails, use the host name from /etc/hosts
#
#######################################################################

getCompleteHostName() {

    # check if host name includes domainname

    hostname=`/usr/bin/hostname`
    echo $hostname | grep "\."
    if [ $? -eq 0 ]; then

        ping $hostname > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo $hostname
        fi

    # check if DNS configured
    elif [ -s /etc/resolv.conf ]; then
        common_name=`env LANG=C LC_ALL=C /usr/sbin/nslookup $hostname`
        if [ $? -eq 0 ]; then
            echo $common_name | sed -e 's/  / /g' -e 's/^.*Name: //' | cut -d" " -f1

        else

            # concatenate hostname and domainname and check if it is valid
            domain=`/usr/bin/domainname`
            ping "$hostname.$domain" > /dev/null 2>&1
            if [ $? -eq 0 ]; then
                echo $hostname.$domain
            else
                #use the IP address from /etc/hosts
                common_name=`grep "$hostname" /etc/hosts | cut -f1`
                echo $common_name
            fi
        fi
    else
        # concatenate hostname and domainname and check if it is valid
        domain=`/usr/bin/domainname`
        ping "$hostname.$domain" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo $hostname.$domain
        else
            #use the IP address from /etc/hosts
            common_name=`grep "$hostname" /etc/hosts | cut -f1`
            echo $common_name
        fi
    fi
}

#########################################################################
#
# Generate the keystore and install it in /etc/sadm/webconsole if it
# has not been generated yet.
# Create a unique id that represents the server machine one which the
# webserver will be running. This will be used to assign uniqueness to
# the certificate being generated. Setting CN to "Unknown" is causing
# some browsers (NS 4.7x) to get confused and others ask for revalidation
# even after the user has accepted the certificate once.
#########################################################################

generateKeystore() {

    KEYSTORE=/etc/sadm/webconsole/keystore

    if [ ! -f "${KEYSTORE}" ]; then

        common_name=`getCompleteHostName`

        ${JAVA_HOME}/bin/keytool -genkey -alias tomcat -keyalg RSA \
            -keypass changeit -storepass changeit \
            -keystore ${KEYSTORE} \
            -dname "CN=$common_name, OU=Solaris Management Products and Tools, O=Sun Microsystems, L=Burlington, ST=Mass, C=US" \
            -validity 2000
        chmod 644 ${KEYSTORE}
    fi
}

########################################################
#
# Main
#
########################################################


# Must be root user to manage the server
#
id=`/bin/id | awk '{print $1}'`
if [ "${id}" != "uid=0(root)" ]; then
    echo "You must be the system's root user to manage the server."
    exit 1
fi



#
# Locate configuration file and execute it.  Try the most obvious
# locations before giving up.
#
WEBBASES="`cd \`dirname $0\`/..; pwd` /usr/sadm"
for w in ${WEBBASES}
do
    CONFIG=${w}/lib/webconsole/lib/.runtimerc
    if [ -f "${CONFIG}" ]; then
	break
    fi
    CONFIG=""
done

if [ ! -n "${CONFIG}" ]; then
    echo "Cannot find configuration file."
    exit 1
fi

 . ${CONFIG}


# CATALINA_BASE must be set
#
if [ ! -n "${CATALINA_BASE}" ]; then
    echo "Unable to locate Console Web Server because CATALINA_BASE"
    echo "is not set in ${CONFIG}."
    exit 1
fi

# CATALINA_HOME must be set
#
if [ ! -n "${CATALINA_HOME}" ]; then
    echo "Unable to locate Tomcat Servlet/JSP Container because CATALINA_HOME"
    echo "is not set in ${CONFIG}."
    exit 1
fi


#
# Setting up LD_LIBRARAY_PATH 
#
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${CATALINA_BASE}/lib
export LD_LIBRARY_PATH



#
# CATALINA_BASE/logs is already a symbolic link to the logs directory in
# "/var", because we can't write logs to (possible read-only) /usr filesystem.
# So make the directory in "/var" if it does not already exist.
#
cd ${CATALINA_BASE}
LOG_DIR=../../../../var/sadm/webconsole/logs
if [ ! -d "${LOG_DIR}" ]; then
    mkdir -p ${LOG_DIR}

    # Must be world-writeable, so server running as "noaccess" can write to it.
    chmod 777 ${LOG_DIR}
fi


# Ensure log file exists and that it's world-writeable because while
# we need to write to it as root, the server will be running as "noaccess"
# and also needs to write to it.
#
LOG_FILE=${CATALINA_BASE}/logs/catalina.out
touch ${LOG_FILE}
chmod 666 ${LOG_FILE}


# And ditto for CATALINA_BASE/work, where Tomcat writes out session info.
#
WORK_DIR=../../../../var/sadm/webconsole/work
if [ ! -d "${WORK_DIR}" ]; then
    mkdir -p ${WORK_DIR}

    # Must be world-writeable, so server running as "noaccess" can write to it.
    chmod 777 ${WORK_DIR}
fi


#
# Execute The Requested Command 
#
case "$1" in

"start")

    # If we have a PID, then we should be already running.  But just
    # in case we were killed directly, we should check that the PID
    # is valid.
    if [ -f ${PIDFILE} ]; then
	PID=`cat ${PIDFILE}`
	if [ -n "`ps -deaf | awk '{print $2}' | grep $PID`" ]; then
	    echo "$0: server (pid ${PID}) already running"
	    exit 0
	fi
	rm -f ${PIDFILE}
    fi

    updateLoginModules
    checkForApps
    shift
    findJava
    setClassPath
    generateKeystore

    # If keystore file does not exist, create it.
    KEYSTORE=/etc/sadm/webconsole/keystore
    if [ ! -f "${KEYSTORE}" ]; then
	${JAVA_HOME}/bin/keytool -genkey -alias tomcat -keyalg RSA \
	    -keypass changeit -storepass changeit \
	    -keystore ${KEYSTORE} \
	    -dname "CN=Unknown, OU=Solaris Management Products and Tools, O=Sun Microsystems, L=Burlington, ST=Mass, C=US" \
	    -validity 2000
	chmod 644 ${KEYSTORE}
    fi

    # Note: java.security.policy must be specified as shown
    # (using '==') so that we use ONLY the specified policy 
    # file (console.policy) and ignore all others.
    SECURITY_ARGS="-Djava.security.manager \
	    -Djava.security.policy==${CATALINA_BASE}/policy/console.policy"

    STARTING="Starting ${VERSION}"
    echo "" >> ${LOG_FILE}
    echo "${STARTING} on `date`" >> ${LOG_FILE}
    logRuntime
    echo "${STARTING}..."

    # Delete the well-known file that the server will create when it's
    # started up.  We use this below to wait for startup to complete.
    #
    rm -f ${SERVER_STARTED_FILE}


    # Following the web-server tradition, start the server as user "noaccess".
    # We do this by writing out the full startup command to a temporary
    # file owned by "noaccess" and with the setUID bit set, and then
    # executing it.

    TMP_SH=/tmp/tomcat.$$
    TMP_PIDFILE=/tmp/pid.$$

    echo "#!/bin/sh" > ${TMP_SH}
    echo "" >> ${TMP_SH}
    echo "${JAVA} -classpath ${CP} \\" >> ${TMP_SH}
    echo "    ${SECURITY_ARGS} \\" >> ${TMP_SH}
    echo "    ${CATALINA_OPTS} \\" >> ${TMP_SH}
    echo "    -Dcatalina.base=${CATALINA_BASE} \\" >> ${TMP_SH}
    echo "    -Dcatalina.home=${CATALINA_HOME} \\" >> ${TMP_SH}
    echo "    -Djava.awt.headless=true \\" >> ${TMP_SH}
    echo "    -Djava.security.auth.login.config=${CATALINA_BASE}/conf/consolelogin.conf \\" >> ${TMP_SH}
    echo "    org.apache.catalina.startup.Bootstrap $@ start \\" >> ${TMP_SH}
    echo "    >> ${LOG_FILE} 2>&1 &" >> ${TMP_SH}
    echo "SERVER_PID=\$!" >> ${TMP_SH}
    echo "echo \${SERVER_PID} > ${TMP_PIDFILE}" >> ${TMP_SH}

    chmod 4544 ${TMP_SH}
    chown noaccess ${TMP_SH}
    /usr/bin/nohup ${TMP_SH} >/dev/null 2>&1

    cp ${TMP_PIDFILE} ${PIDFILE}
    rm -f ${TMP_PIDFILE}


    # Since we started the server in the background, we should wait
    # until it has started up before continuing.  We wait until a
    # well-known file gets created.  Apply a timeout in case the server 
    # never starts properly.  This basically signals that the registration
    # servlet has completed.
    #
    waitOnFile ${SERVER_STARTED_FILE} 20 -f 1

    # When we get here, the registration is complete such that the server
    # will respond to HTTP requests.

    # If no classes for console jsp exist, then copy in pre-compiled classes.
    # But must 1st wait to make sure the hierarchy is boostrapped by Tomcat.
    #
    cd ${CATALINA_BASE}
    waitOnFile ${WORK_DIR}/localhost/console 20 -d 0
    if [ -d ${WORK_DIR}/localhost/console ]; then
	classes=`find ${WORK_DIR}/localhost/console -name "*.class" >/dev/null 2>&1`
	if [ ! -n "${classes}" ]; then
	    find . -name "*.class" | grep /jsp | \
		cpio -pdm ${WORK_DIR}/localhost > /dev/null 2>&1
	    for i in `find ${WORK_DIR}/localhost -name "*.class"`; do
		chmod 644 $i
	    done
	    chown -R noaccess:other ${WORK_DIR}
	fi
    fi

    # When we get here, the server is ready.

    echo "See ${LOG_FILE} for server logging information"
    rm ${TMP_SH}
    ;;

"stop")

    # If we don't have a PID, then we should not be running.
    # But don't output an error message if we're in the middle
    # of a packaging environment, where most likely an uninstall
    # is taking place.
    if [ ! -f ${PIDFILE} ]; then
	if [ ! -n "${PKGINST}" ]; then
	    echo "$0: server not running - ${PIDFILE} does not exist"
	fi
	exit 0
    fi

    shift
    findJava
    setClassPath

    STOPPING="Shutting down ${VERSION}"
    echo "" >> ${LOG_FILE}
    echo "${STOPPING} on `date`" >> ${LOG_FILE}
    logRuntime
    echo "${STOPPING}..."

    ${JAVA} -classpath ${CP} \
	${CATALINA_OPTS} \
	-Dcatalina.base=${CATALINA_BASE} \
	-Dcatalina.home=${CATALINA_HOME} \
	org.apache.catalina.startup.Bootstrap "$@" stop >/dev/null 2>&1

    rm -f ${PIDFILE}
    ;;

"enable")
        # set ENABLE to "yes" in /etc/default/webconsole
        # if file does not exist create it and set the value of ENABLE
        # otherwise simply set the value

        writeText "yes"
        exit 0
        ;;

"disable")
        # set ENABLE to "no" in /etc/default/webconsole

        writeText "no"
	exit 0
	;;

"restart")
    shift
    cd ${SAVECWD}
    $0 stop
    $0 start $*
    ;;
    
"-v" | "--version")
   echo $VERSION
   ;;

*)
    echo "Usage: ${0} ( start | stop | restart | enable | disable | help | -v )"
    echo "Commands:"
    echo "  start              Start Catalina in a separate window"
    echo "  stop               Stop Catalina"
    echo "  restart            stop followed by start"
    echo "  enable             set the webserver to start at boot time"
    echo "  disable            disable webserver start up at boot time"
    echo "  help               print this usage statement"
    echo "Options:"
    echo "  -v, --version      print the version of the installed console"
    exit 1
    ;;

esac
