#!/bin/bash
#----------------------------------------------------------------------------
# 
# wccproxy
#
# This Bash shell script starts WCCProxy processes. It exports the
# environment variables we need, then starts the java vm
# (unless overridden), passing optional parameters.
#
# Usage:
# (not all of these are shown in the Usage echo's below, to hide the
# options intended for expert users)
# 
# wccproxy [help]
#     Show this help.
# wccproxy start [compete|nice <number>] 
#     Start the WCCProxy Director process.
#     compete arg specifies to start WCCProxy process at a higher priority
#     to compete with other system processes.
#     nice arg allows user to specify nice level of director process.
#     negative numbers indicate higher priority. See the nice man page for
#     further explanation.
#     If the command is 'desta start wccproxy' then the script will start 
#     the WCCProxy program and exit, the director will not be started.
# wccproxy stop 
#     Shut down the WCCProxy Director process and all WCCProxy-connected 
#     processes.
# wccproxy status 
#     Shows the status of the WCCProxy process.
# wccproxy priority [compete|low]
#     Shows the system priority of the WCCProxy  process
#     compete or low option changes priority of WCCProxy process.
#
# You can set the following environment variables to change the behavior.
# This script will assign them to proper installed defaults if not set
# by the user.
#
# WCCPROXY_HOME
#     The top-level directory of Compaq Service Tools. By default,
#     assigned to the parent directory of this script's real directory
#     (symbolic links are followed to arrive at the script's real
#     directory).
#
#
# WCCProxy's Use Of LD_LIBRARY_PATH :
#
# The "wccproxy" script will create the LD_LIBRARY_PATH for this process based
# on default behavior that can be modified by the user (any caller of this
# script, which could be another script). The LD_LIBRARY_PATH will contain
# (in order):
#
# 1. The $SVCTOOLS_SHARE_EXTRA, if defined by the user (see below).
# 2. The $SVCTOOLS_SHARE, created here or overriden by the user
#    (see below). 
# 
# LD_LIBRARY_PATH
#     Any existing LD_LIBRARY_PATH will be *ignored* by this script! This
#     is to prevent corruption of WCCPROXY's LD_LIBRARY_PATH by identically
#     named but different shared object libraries in directories that the
#     user has defined on the LD_LIBRARY_PATH. To explicitly add shared
#     library directories to WCCPROXY's LD_LIBRARY_PATH, define 
#     SVCTOOLS_SHARE_EXTRA (below). To override the default directory
#     used by WCCPROXY, override SVCTOOLS_SHARE (below).
#
# SVCTOOLS_SHARE
#     The colon-separated list of directories containing all Service 
#     Tools' shared object files. By default, assigned to be the directory
#     $WCCPROXY_HOME/common/share. Define SVCTOOLS_SHARE only if there is a reason
#     *not* to use the shared objects in the default directory, but also be
#     aware that the installation of WCCPROXY products creates symbolic links
#     to its libraries in /usr/shlib. These links will be found in the 
#     absence of LD_LIBRARY_PATH, unless those links are changed/moved.
#
# SVCTOOLS_SHARE_EXTRA
#     The colon-separated list of directories containing additional shared
#     objects not found in $WCCPROXY_HOME/common/share but required by this
#     process. Empty by default. If set by the user, the contents will be
#     prepended to the LD_LIBRARY_PATH created by WCCPROXY.
#
# WCCPROXY Status File
#     The Director creates a status file at startup which contains the status
#     of the director. This script kicks off the Director process and then
#     checks the contents of the status file to see if the director has 
#     started correctly. It then displays a message to the console informing
#     the user if the director started correctly or not. 
#----------------------------------------------------------------------------
# Uncomment this line to show what's going on, or (better) use the
# wccproxy_g debug variant of this script instead (located in the same 
# directory as the wccproxy script).
#set -x

# Make all new files have no permissions for group and world.
#umask 077

# Remove all exported aliases so that ksh built-in commands do what we
# expect them to do.
#unalias -a

#ReadRegistry ()
#  Read the` value associated with the specified key in the registry.
#{
#    REGISTRY_FILE=$SVCTOOLS_HOME/specific/desta/config/DESTA.REG
#    if [ -r $REGISTRY_FILE ]
#    then
#        REGISTRY_VALUE=`/bin/grep "^ *$REGISTRY_KEY *=" $REGISTRY_FILE`
#        REGISTRY_VALUE=`echo $REGISTRY_VALUE | /bin/sed 's/.*= *//'`
#        REGISTRY_VALUE=`echo $REGISTRY_VALUE | /bin/sed 's/ *$//'`
#    fi
#}


#  Build the WCCPROXY environment variables based on the real location of
#  this shell script, or the user's overrides.

#  Derive the WCCPROXY_HOME environment variable if not overridden, and
#  validate the directory.
STARTING_DIR=`/bin/pwd`

if [ "$WCCPROXY_HOME" = "" ]
then
    #  Find my real directory, even if $0 is really a symbolic link
    MYREALDIR=`/bin/ls -l $0 | /bin/cut -f 2 -d '>' | /bin/cut -f 2 -d ' '`

    if [ "$MYREALDIR" = "" ]; then
        # Not a symbolic link
        WCCPROXY_HOME=`/usr/bin/dirname $0`/../../../
    else
        # Symbolic link, use the directory to which it points
        WCCPROXY_HOME=`/usr/bin/dirname $MYREALDIR`/../../../
    fi

fi

if [ ! -d "$WCCPROXY_HOME" ]
then
    echo "$0 Error: $WCCPROXY_HOME directory does not exist."
    exit 642
fi

#  The following is to fix an anomaly whereby if this script is executed
#  in a dir below where WCCPROXY_HOME is to be, it ends up getting 
#  assigned a relative path instead of an absolute which can cause
#  problems if a class file is expecting and requires an absolute path.
cd $WCCPROXY_HOME
WCCPROXY_HOME=`/bin/pwd`
cd $STARTING_DIR
export WCCPROXY_HOME


#  Define the directory for WCCPROXY shared libraries, if not defined already.
if [ "$SVCTOOLS_SHARE" = "" ]
then
    SVCTOOLS_SHARE=$WCCPROXY_HOME/common/wccproxy/share
fi
export LD_LIBRARY_PATH=$SVCTOOLS_SHARE_EXTRA:$SVCTOOLS_SHARE

# The JNIRoot Launcher executable
WCCPROXY_EXE=WCCProxy

# The JNIRoot Launcher PID file
WCCPROXY_PID_FILE=$WCCPROXY_HOME/specific/wccproxy/data/wccproxy.pid

# Set the ulimit to well below the value that causes WEBES processes to 
# crash with segmentation violations (around 3,500,000) and lower than
# the 4,194,304 default value on Sierra clusters that causes the Java VM
# to refuse to run, claiming the stack limit is too high.
# We don't actually need it any higher than the default e.g. 2048 on
# Unix 4.x non-clustered machines, we do this only to prevent the too-high
# error from the Java VM.
ulimitsMAX=1000000
ulimitsNOW=`ulimit -s`

# check if the stack limit is "unlimited"
if [ $ulimitsNOW = unlimited ]
then
    ulimitsNOW=$ulimitsMAX
else
    # Ensure integer format for ulimitsNOW
    # this printf call uses the format string %15.0f
    # because sometimes the number is so large that ulimit 
    # returns it in scientific notation, like 2.345e+09
    # using the floating point format string ensures an integer 
    # format so that the comparison work.
    ulimitsNOW=`/usr/bin/printf "%15.0f" $ulimitsNOW`
fi

if [ $ulimitsNOW -ge $ulimitsMAX ]
then
    ulimit -s $ulimitsMAX
fi

# How long (in seconds) this script waits for the Director to start 
# before aborting
WCCPROXY_TIMEOUT=80
# How long (in seconds) this script waits for the Director to start 
# before reassuring the user that we're still waiting.
WCCPROXY_REASSURE=20


function checkWCCProxyProcess {
	# return a value of 0 if JNIRoot process is running
	# or a value > 0 if it is not running

	typeset STATE  # local variable
    	STATE=99   # unknown state

    	if [ ! -e $WCCPROXY_PID_FILE ] # pid file not found. 
    	then
		#ps -ef | grep -v grep | grep -q $WCCPROXY_EXE
		ps -C $WCCPROXY_EXE|grep -q $WCCPROXY_EXE
		# $? is 0 if the process named $WCCPROXY_EXE is found, 
		# > 0 if no process found with that name.
		STATE=$?

    	else
		PID=`tail -n +1 $WCCPROXY_PID_FILE`
		ps -p $PID | grep -q $WCCPROXY_EXE  
		# $? is 0 if a PID is found, > 0 if no PID found
		STATE=$?
	fi
    	
    	return $STATE
}


function setProcessUlimit {
    # Compute 1/2 of current total swap file allocation and
    # Set addressspace/vmemory hard limit for this process and children
    # Unless current limit is lower

    # Also set the data segment limit to be the lesser of the virtual 
    # memory limit or the system's hard limit for the data segment

    # printf calls in this function use the format string %15.0f
    # because sometimes the number is so large that ulimit 
    # returns it in scientific notation, like 2.345e+09
    # using the floating point format string ensures an integer 
    # format so that the comparisons work.

    ulimitvOLD=`ulimit -v`

    ulimitvNEW=`/sbin/swapon -s | \
	/bin/grep partition | \
	/bin/awk '{print $3/2}'
        #-F[(MG]' \
	#'/MB/{print $3*1000/2} \
	#/GB/{print $3*1000000/2}'`
    # Ensure integer format for ulimitvNEW
    ulimitvNEW=`/usr/bin/printf "%15.0f" $ulimitvNEW`

    # check if the VM limit is "unlimited"
    if [ $ulimitvOLD = unlimited ]
    then 
		# set VM limit equal to the computed VM limit.
		ulimitvOLD=$ulimitvNEW
	else
		# it's not unlimited
		# Ensure integer format for ulimitvOLD
		ulimitvOLD=`/usr/bin/printf "%15.0f" $ulimitvOLD`
    fi
    ulimitdHARD=`ulimit -H -d`
    # check if the hard data limit is "unlimited"
    if [ $ulimitdHARD = unlimited ]
    then
        # set the data hard limit to the lesser of the system's virtual memory
        # limit or the computed virtual memory limit
        if [ $ulimitvOLD -gt $ulimitvNEW ]
        then
            ulimitdHARD=$ulimitvNEW
        else
            ulimitdHARD=$ulimitvOLD
        fi
    fi
    # Ensure integer format for ulimitdHARD
    ulimitdHARD=`/usr/bin/printf "%15.0f" $ulimitdHARD`
    if [ $ulimitvOLD -gt $ulimitvNEW ]
    then
        ulimit -v $ulimitvNEW
        # Now set data segment limit
        if [ $ulimitvNEW -gt $ulimitdHARD ]
        then
	    ulimit -d $ulimitdHARD
        else
    	    ulimit -d $ulimitvNEW
        fi
    else
        if [ $ulimitvOLD -gt $ulimitdHARD ]
        then
            ulimit -d $ulimitdHARD
        else
            ulimit -d $ulimitvOLD
        fi
    fi
}

wccproxy_start () 
{
	checkWCCProxyProcess
	STATE=$?
	if (($STATE == 0)) # JNIRoot launcher is already running
	then
		echo "WCCProxy is already running."
	else
		# delete the WCCService.pids file - it grows without bound otherwise
		/bin/rm -f $WCCPROXY_HOME/specific/wccproxy/logs/WCCService.pids

		echo "Starting WCCProxy."
		/usr/bin/nohup nice $WCCPROXY_HOME/common/wccproxy/share/$WCCPROXY_EXE >> $WCCPROXY_HOME/specific/wccproxy/logs/WCCProxy.Start 2>&1 &
#/dev/null  2>&1 &		
		LAUNCHER_PID=$!
		echo $LAUNCHER_PID > $WCCPROXY_PID_FILE
	fi

    # Create the Linux lock file for this daemon so that Linux shutdown
    # will know to stop it. (OK if the WCCProxy doesn't start up or dies,
    # because it's OK to call "wccproxy stop" even if no WCCProxy is running.)
    # OK if the file already exists.
    touch /var/lock/subsys/wccproxy
}

wccproxy_stop ()
{
	checkWCCProxyProcess
	STATE=$?
	if (($STATE == 0)) # JNIRoot launcher is running
	then
		echo "Stopping WCCProxy."
		$WCCPROXY_HOME/common/wccproxy/share/$WCCPROXY_EXE -stop
	else
		echo "The WCCProxy is NOT running."
		echo "Can't stop it."
	fi
}

# This function will kill the WCCProxy and any running agents
wccproxy_kill ()
{
        typeset -i NUM
        typeset -i COUNT

        # first kill the WCCProxy process
        PROCLIST=`ps -e -o pid,comm | grep -v grep | grep WCCProxy | gawk '{print $1}' | tr '\n' ' ' `
        NUM=`echo $PROCLIST | wc -w`
        (( NUM=NUM+1 ))
        COUNT=1
        while (( COUNT < NUM ))
        do
                kill -9 `echo $PROCLIST | cut -f $COUNT -d ' '`
                echo "Killed WCCProxy. PID: " `echo $PROCLIST | cut -f $COUNT -d ' '`
                (( COUNT=COUNT+1 ))
        done

        # Next kill any CAAgents processes that are running
        PROCLIST=`ps -e -o pid,comm | grep -v grep | grep CAAgents | gawk '{print $1}' | tr '\n' ' ' `
        NUM=`echo $PROCLIST | wc -w`
        (( NUM=NUM+1 ))
        COUNT=1
        while (( COUNT < NUM )) 
        do
                kill -9 `echo $PROCLIST | cut -f $COUNT -d ' '`
                echo "Killed CAAgents PID: " `echo $PROCLIST | cut -f $COUNT -d ' '`
                (( COUNT=COUNT+1 ))
        done

        # Lastly kill any WCCAgents that are running
        PROCLIST=`ps -e -o pid,comm | grep -v grep | grep WCCAgents | gawk '{print $1}' | tr '\n' ' ' `
        NUM=`echo $PROCLIST | wc -w`
        (( NUM=NUM+1 ))
        COUNT=1
        while (( COUNT < NUM ))
        do
                kill -9 `echo $PROCLIST | cut -f $COUNT -d ' '`
                echo "Killed WCCAgents PID: " `echo $PROCLIST | cut -f $COUNT -d ' '`
                (( COUNT=COUNT+1 ))
        done

   # Remove the lock file for this daemon so that Linux shutdown doesn't
   # try to stop it.
   rm -f /var/lock/subsys/wccproxy
}


case "$1" in

    'status')
        # if the command is ' status wccproxy' we will print out the 
	# status of the WCCProxy program also.

	checkWCCProxyProcess
	PROXYSTATE=$?

	if (($PROXYSTATE == 0)) 
	then
		echo "WCCProxy is running."
	else
		echo "WCCProxy is NOT running."
	fi

	exit $PROXYSTATE
        ;;

    'priority')	    
	# Checks or sets the system priority of the director process.
	# USAGE:	    
	# 'wccproxy priority' simply prints out the director's PID, 	    
	# priority and nice level and exits.
	#	    
	# 'wccproxy priority compete' renices the director's priority to a 
	# nice level of 0. This allows the director process to compete
	# on a level playing field with other system processes.
	#	    
	# 'wccproxy priority low' renices the director process to a nice level
	# of 10. This is the default priority for the director process.
	#
	
	PID=`sed -n '2p' $STATUS_FILE` 
	typeset -i PRI
	typeset -i NICE
	typeset -i NICEPARAM
	PRI=`ps -e -o pid,pri,nice|grep $PID|gawk '{print $2}'`
	NICE=`ps -e -o pid,pri,nice|grep $PID|gawk '{print $3}'`
	echo "Director PID = $PID. Priority = $PRI. Nice level = $NICE."

	if [ "$2" = "compete" ]
	then
		echo "resetting director process priority to 'compete'"
		NICEPARAM=-$NICE
		`renice -n $NICEPARAM $PID`
	elif [ "$2" = "low" ]
	then
		echo "resetting director process priority to 'low'"
		NICEPARAM=10-$NICE
		`renice -n $NICEPARAM $PID`
	fi
	;;
    'start')
	# if the command is ' start wccproxy' then start the WCCProxy program 
	# and exit.
	wccproxy_start
	# Wait one second to allow proxy to completely start up
	sleep 1
	checkWCCProxyProcess
	PROXYSTATE=$?

	if (($PROXYSTATE == 0)) 
	then
		echo "WCCProxy is running."
	else
		echo "WCCProxy is NOT running."
	fi

	# Check if the user wants to manipulate the director process
	# priority.
	if [ "$2" = "nice" ]
	then

	    if (($# < 3)) # Check for three parameters
	    then
		echo "You must specify a nice level when using the nice option."
		echo "Using default nice level."
		NICE="nice"
	    else #TODO Linux
		# check that $3 is a number (negative numbers are OK)
		#if [[ $3 = ?([+-])+([[:digit:]]) ]]
		#then
		#    NICE="nice -n $3"
		#else
		#    echo "Nice level must be a number."
		#    echo "using default nice level"
		    NICE="nice"
		#fi
	    fi

	elif [ "$2" = "compete" ]
	then
		NICE=""
	else
        	NICE="nice"
	fi

	setProcessUlimit
	exit $PROXYSTATE
	;;

    'stop')
	# if the command is ' stop wccproxy' then stop the WCCProxy program 
	# and exit.
	wccproxy_stop
	# Wait one second for WCCProxy to completely stop
	sleep 1
	wccproxy_kill
	exit 0
	;;

    'sysinfo')
	sysInfoUsage="Syntax error. Usage: WCCProxy sysinfo [ out filename.txt ]"
	if [ "$2" = "" ]
	then
		sysInfoFile=WCCProxy_sysinfo.txt
	else

		if [ "$2" = "out" ]
		then

			if [ "$3" = "" ]
			then
				echo "$sysInfoUsage"
				exit 50
			else    
				sysInfoFile=$3
			fi

		else
			echo "$sysInfoUsage"
			exit 50
		fi
	fi

	if [ -e $sysInfoFile ]
	then
		echo "$sysInfoFile already exists, exiting."
		exit 706
	fi

	# Enable noclobber to ensure we don't overwrite an existing file.
	set -C
	echo "Dumping system information into $sysInfoFile"
	echo "This may take a while..."
	# print out some information on this systems settings
	echo "System Information:" > $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Identification:" >> $sysInfoFile 2>&1
	/bin/uname -a >> $sysInfoFile 2>&1
	/bin/date >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Swap space:" >> $sysInfoFile 2>&1
	/sbin/swapon -s >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Default process limits:" >> $sysInfoFile 2>&1
	ulimit -a >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Hard process limits:" >> $sysInfoFile 2>&1
	ulimit -H -a >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "vmstat:" >> $sysInfoFile 2>&1
	/usr/bin/vmstat  >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Environment variables:" >> $sysInfoFile 2>&1
	set >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Network status:" >> $sysInfoFile 2>&1
	/bin/netstat -i >> $sysInfoFile 2>&1
	/bin/netstat -r >> $sysInfoFile 2>&1
	/bin/netstat -rn >> $sysInfoFile 2>&1
	/bin/netstat >> $sysInfoFile 2>&1
	/bin/netstat -a >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Ping myself:" >> $sysInfoFile 2>&1
	/bin/ping -c3 localhost >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Boot messages:" >> $sysInfoFile 2>&1
	/bin/cat /var/log/boot.log >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Kernel messages:" >> $sysInfoFile 2>&1
	/bin/cat /var/log/ksyms.0 >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "System messages:" >> $sysInfoFile 2>&1
	/bin/cat /var/log/messages >> $sysInfoFile 2>&1	
	echo "=================================" >> $sysInfoFile 2>&1
	echo "File systems:" >> $sysInfoFile 2>&1
	/bin/df -k >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Installed products:" >> $sysInfoFile 2>&1
	/bin/rpm -qa >> $sysInfoFile 2>&1

	if [ -x /usr/bin/dsn ]
	then
		echo "=================================" >> $sysInfoFile 2>&1
		echo "DSNlink info:" >> $sysInfoFile 2>&1
		/usr/bin/dsn version >> $sysInfoFile 2>&1
	fi

	echo "=================================" >> $sysInfoFile 2>&1
	echo "WEBES release:" >> $sysInfoFile 2>&1
	/bin/cat $WCCPROXY_HOME/common/wccproxy/release.txt >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "WEBES directories:" >> $sysInfoFile 2>&1
	/bin/ls -alRL /usr/opt/hp/svctools >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Running WCCProxy process:" >> $sysInfoFile 2>&1
	/bin/ps ugxww | /bin/grep WCCProxy | /bin/grep -v grep >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "Open files" >> $sysInfoFile 2>&1
	/usr/sbin/lsof +D $WCCPROXY_HOME >> $sysInfoFile 2>&1
	echo "=================================" >> $sysInfoFile 2>&1
	echo "End of WCCProxy sysinfo output." >> $sysInfoFile 2>&1
	echo "Complete."
    ;;
  'WCCService')
#    set -x
    /usr/bin/nohup nice $2 $3 $4 $5 $6 $7 $8 $9 >> $WCCPROXY_HOME/specific/wccproxy/logs/WCCServices.log 2>&1 &
    WCCSpid=$!
    echo $WCCSpid >> $WCCPROXY_HOME/specific/wccproxy/logs/WCCService.pids
    ;;
    'killwccproxy')
    wccproxy_kill
    exit 0
    ;;

  'version')
    $WCCPROXY_HOME/common/wccproxy/share/$WCCPROXY_EXE -v
    exit 0
    ;;

    *)
	#  Unknown or "help" command
      if [ "$1" = "" ]
      then
        echo "Error 386: Insufficient arguments."
	more $WCCPROXY_HOME/common/wccproxy/docs/clihelp/wccproxy_summary.txt
      else

        if [ "$1" = "help" ]
        then
	  more $WCCPROXY_HOME/common/wccproxy/docs/clihelp/wccproxy_summary.txt
        else
          if [ ! "$1" = "help" ]
          then
              echo "Error 50: Illegal arguments."
              more $WCCPROXY_HOME/common/wccproxy/docs/clihelp/wccproxy_summary.txt
          fi
        fi
      fi
	;;
	
 esac

# End of file
