#! /bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2007 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
#*===========================================================================*/
#*                                                                           */
#* Module Name:  rmcctrl                                                     */
#*                                                                           */
#* Description:                                                              */
#*      Script to manage the Resource Monitor & Control Daemon as            */
#*      an SRC subsystem.                                                    */
#*                                                                           */
#*===========================================================================*/
#*   @(#)37   1.35   src/rsct/rmc/mcdaemon/rmcctrl.sh, mcdaemon, rsct_relgh, relghs001a 3/22/07 09:42:24 

# Set path to known value
PATH=/usr/sbin/rsct/bin:/usr/bin:/usr/sbin:/bin
export PATH

SS_PATH=/usr/sbin/rsct/bin			# path to subsystem daemons
CDEF_PATH=/usr/sbin/rsct/cfg/rmdefs	# path to cdef files
SUBSYS=ctrmc						# name of subsystem
SUBSYSGRP=rsct						# name of subsystem's group
RMGRP=rsct_rm						# group name for all RSCT resource managers
PROG=rmcd							# name of subsystem daemon
SPROG=rmcd_start					# name of subsystem daemon startup program
WAITTIME=30							# value of -w flag on mkssys
WAITLIMIT=40						# number of seconds to wait for
									# subsystems to stop
QUIECELIMIT=6						# number of seconds to ensure subsystems
									# are stopped

# get cluster name (1st token in lsclcfg ouput)

CTNAME=$(LC_ALL=C lsclcfg -x 2> /dev/null | sed -n -e"1s/^\([^ ]*\) .*$/\1/p")

CTNAME=${CTNAME:-IW}				# ensure a rational value

CFGDIR=/var/ct/$CTNAME/cfg			# path to directory that will contain cdb
CDBBASE=mc.cdb
CT_CLASS_IDS=/usr/sbin/rsct/cfg/ct_class_ids
START_PORT_FILE=/var/ct/cfg/ctrmc.rpe	# rpe == remote port enable
MSG_POLICY_FILE=/var/ct/cfg/ctrmc.msgp	# msgp == client message policy
DMSG_POLICY_FILE=/var/ct/cfg/ctrmc.dmsgp	# dmsgp == daemon message policy
TIMEOUT_OPTS_FILE=/var/ct/cfg/ctrmc.topts	# timeout options
RMCDBDIR=/var/ct/cfg				# directory containing RM CDBs

CMD=$(basename $0)
CTMSG=${SS_PATH}/ctdspmsg
MSGMAPPATH=/usr/sbin/rsct/msgmaps
export MSGMAPPATH

# sed string to extract subsystem state from "lssrc -s <subsys>" output
PARSE_SRC_STATE="-e1d;s/.* \([a-zA-Z0-9]*\)$/\1/"

# sed string to extract subsystem PIDs from "lssrc -g <subsys>" output
PARSE_SRC_PIDS="s/^ *[^ ]* *[^ ]* *\([0-9]*\) *active/\1/p"

# function to determine if any subsystems are active

function active_subsys {
	typeset ActiveSubsys=n

	if LC_ALL=C lssrc -g ${SUBSYSGRP} 2> /dev/null | \
							grep -E 'active|warned' > /dev/null 2>&1
	then
		ActiveSubsys=y
	fi

	if LC_ALL=C lssrc -g ${RMGRP} 2> /dev/null | \
							grep -E 'active|warned' > /dev/null 2>&1
	then
		ActiveSubsys=y
	fi

	print $ActiveSubsys

	return
}

# function to set/reset timeout options

function timeout_option {
	typeset MatchOption=n
	typeset WroteFile=n

	keyword=$1
	keyvalue=$2

	tmp_file=$TIMEOUT_OPTS_FILE.$$
	rm -f $tmp_file

	if [[ -s $TIMEOUT_OPTS_FILE ]]
	then
		while read Flag junk
		do
			case $Flag in
				MSG_TIMEOUT* )
					if [[ "$keyword" = "MSG_TIMEOUT" ]]
					then
						MatchOption=y
						if [[ -n "$keyvalue" ]]
						then
							print "MSG_TIMEOUT=$keyvalue" >> $tmp_file
							WroteFile=y
						fi
					else
						print "$Flag" >> $tmp_file
						WroteFile=y
					fi
					;;
				START_TIMEOUT* )
					if [[ "$keyword" = "START_TIMEOUT" ]]
					then
						MatchOption=y
						if [[ -n "$keyvalue" ]]
						then
							print "START_TIMEOUT=$keyvalue" >> $tmp_file
							WroteFile=y
						fi
					else
						print "$Flag" >> $tmp_file
						WroteFile=y
					fi
					;;
				CMD_TIMEOUT* )
					if [[ "$keyword" = "CMD_TIMEOUT" ]]
					then
						MatchOption=y
						if [[ -n "$keyvalue" ]]
						then
							print "CMD_TIMEOUT=$keyvalue" >> $tmp_file
							WroteFile=y
						fi
					else
						print "$Flag" >> $tmp_file
						WroteFile=y
					fi
					;;
				CMD_THRESHOLD* )
					if [[ "$keyword" = "CMD_THRESHOLD" ]]
					then
						MatchOption=y
						if [[ -n "$keyvalue" ]]
						then
							print "CMD_THRESHOLD=$keyvalue" >> $tmp_file
							WroteFile=y
						fi
					else
						print "$Flag" >> $tmp_file
						WroteFile=y
					fi
					;;
				CMD_AUTHENT_ENABLE )
					if [[ "$keyword" = "CMD_AUTHENT_ENABLE" ]]
					then
						MatchOption=y
						if [[ -n "$keyvalue" ]]
						then
							print "CMD_AUTHENT_ENABLE" >> $tmp_file
							WroteFile=y
						fi
					else
						print "$Flag" >> $tmp_file
						WroteFile=y
					fi
					;;
			esac
		done < $TIMEOUT_OPTS_FILE
	fi

	if [[ "$MatchOption" = "n" && -n "$keyvalue" ]]
	then
		if [[ "$keyword" = "CMD_AUTHENT_ENABLE" ]]
		then
			print "$keyword" >> $tmp_file
		else
			print "$keyword=$keyvalue" >> $tmp_file
		fi
		WroteFile=y
	fi

	if [[ "$WroteFile" = "y" ]]
	then
		mv -f $tmp_file $TIMEOUT_OPTS_FILE
	else
		rm -f $TIMEOUT_OPTS_FILE
	fi

	return
}

# function to wait for "first" processing to complete (only on Linux)
# However, do not wait forever

FIRST=/var/ct/first_start
FIRST_LIMIT=36
FIRST_SLEEP=5

function wait_for_first {

	if [[ $OSname = "Linux" ]]
	then
		# set loop limit

		(( i = ${FIRST_LIMIT} ))

		while (( $i > 0 ))
		do
			if [[ -a $FIRST ]]
			then
				sleep $FIRST_SLEEP
			else
				return
			fi

			(( i = $i - 1 ))
		done
	fi

	return
}

# get name of Operating System. How the RMC subsystem is started at bootup
# is OS dependent.

OSname=$(uname -s)
if [[ -z $OSname ]]
then
	OSname=unknown_OS
fi

# mainline code

# Parse command line

Argcount=0
while getopts ":aAskKdm:M:pPqQzt:u:v:w:xTUVWXh" opt
do
	case $opt in
		a )	Op=add;             Argcount=$((Argcount + 1));;
		A )	Op=Add;             Argcount=$((Argcount + 1));;
		s )	Op=start;           Argcount=$((Argcount + 1));;
		k )	Op=stop;            Argcount=$((Argcount + 1));;
		K )	Op=stopall;         Argcount=$((Argcount + 1));;
		d )	Op=delete;          Argcount=$((Argcount + 1));;
		m ) Op=setmsgpolicy; MsgPolicy=$OPTARG;
								Argcount=$((Argcount + 1));;
		M ) Op=setdmsgpolicy; MsgPolicy=$OPTARG;
								Argcount=$((Argcount + 1));;
		p )	Op=startport;       Argcount=$((Argcount + 1));;
		P )	Op=stopport;        Argcount=$((Argcount + 1));;
		q )	Op=delaystartport;  Argcount=$((Argcount + 1));;
		Q )	Op=delaystopport;   Argcount=$((Argcount + 1));;
		z )	Op=stopwait;        Argcount=$((Argcount + 1));;
		t ) Op=set_topt; TimeOptArg=$OPTARG;
								Argcount=$((Argcount + 1));;
		u ) Op=set_uopt; TimeOptArg=$OPTARG;
								Argcount=$((Argcount + 1));;
		v ) Op=set_vopt; TimeOptArg=$OPTARG;
								Argcount=$((Argcount + 1));;
		w ) Op=set_wopt; TimeOptArg=$OPTARG;
								Argcount=$((Argcount + 1));;
		x ) Op=set_xopt;		Argcount=$((Argcount + 1));;
		T ) Op=reset_topt;		Argcount=$((Argcount + 1));;
		U ) Op=reset_uopt;		Argcount=$((Argcount + 1));;
		V ) Op=reset_vopt;		Argcount=$((Argcount + 1));;
		W ) Op=reset_wopt;		Argcount=$((Argcount + 1));;
		X ) Op=reset_xopt;		Argcount=$((Argcount + 1));;

		h ) $CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
				 exit 0;;
		? ) $CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
				 exit 1;;
	esac
done

if ((Argcount == 0))
then
	$CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
	exit 1
fi

if ((Argcount > 1))
then
	$CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
	exit 1
fi

case $Op in

# Add the RMC subsystem to the SRC, /etc/inittab and copy the CDB

add | Add )
	# Ensure subsystem is stopped if it is already in SRC

	state=$(LC_ALL=C lssrc -s "$SUBSYS" | sed "$PARSE_SRC_STATE")
	if [[ -n "$state" && "$state" = "active" ]]
	then
		$CTMSG rmcctrl ct_rmc.cat EMSGG_Subsystem_Must_Be_Stopped \
				$CMD $SUBSYS
		exit 1
	fi

	SRC_args=

	if [[ ! -x $SS_PATH/$SPROG ]]
	then
		$CTMSG rmcctrl ct_rmc.cat EMSGG_Not_Executable $CMD $SS_PATH/$SPROG
		exit 1
	fi

	if [[ ! -x $SS_PATH/$PROG ]]
	then
		$CTMSG rmcctrl ct_rmc.cat EMSGG_Not_Executable $CMD $SS_PATH/$PROG
		exit 1
	fi

	rmssys -s $SUBSYS >/dev/null		# ensure subsystem is out of SRC

	ODMDIR=/etc/objrepos mkssys -s $SUBSYS -a "$SRC_args" -p $SS_PATH/$SPROG -u 0 \
			-i /dev/null -o /dev/null -e /dev/null \
			-R -Q -K -d -w $WAITTIME -G $SUBSYSGRP

	if [[ $? -ne 0 ]]
	then
		$CTMSG rmcctrl ct_rmc.cat EMSGG_Could_Not_Add $CMD $SUBSYS SRC
		exit 1
	fi

	# if this is an AIX system, RMC is started out of inittab at boot

	if [[ $OSname = "AIX" ]]
	then

		# Add an entry to the inittab file for this subsystem, if it is not
		# already there. The new entry will be put at the end of /etc/inittab

		lsitab $SUBSYS > /dev/null 2>&1
		if (( $? != 0 ))                # if entry not there
		then
			mkitab \
			"$SUBSYS:2:once:/usr/bin/startsrc -s $SUBSYS > /dev/console 2>&1" \
			> /dev/null 2>&1
			if (( $? != 0))
			then
				$CTMSG rmcctrl ct_rmc.cat EMSGG_Could_Not_Add $CMD \
						$SUBSYS inittab
				exit 1
			fi
		fi
	fi

	# if this is a Linux system, RMC is started/stopped by the rc script
	# mechanism at boot or when the runlevel changes

	if [[ $OSname = "Linux" ]]
	then
		if ! $SS_PATH/ctinitmgr -a $SS_PATH/rc_$SUBSYS $SUBSYS
		then
			# NEED TO DO: create real error message
			echo "Cannot add $SUBSYS to init script structure"
			exit 1
		fi
	fi

	# remove any RM CDBs. This ensures that RMs will read only those
	# newly created by the RMC subsystem now being added.

	rm -f $RMCDBDIR/mc.*.cdb

	# ensure the RMC remote port numbers are in /etc/services

	TMPSVCS=/etc/services.tmp.$$
	cp /etc/services $TMPSVCS
	Flag=0

	if ! grep 'rmc[ 	][ 	]*[0-9][0-9]*/tcp' /etc/services > /dev/null 2>&1
	then
		print "rmc\t\t657/tcp" >> $TMPSVCS
		Flag=1
	fi

	if ! grep 'rmc[ 	][ 	]*[0-9][0-9]*/udp' /etc/services > /dev/null 2>&1
	then
		print "rmc\t\t657/udp" >> $TMPSVCS
		Flag=1
	fi

	if [[ $Flag = 1 ]]
	then
		mv -f $TMPSVCS /etc/services
	else
		rm -f $TMPSVCS
	fi

	# start the subsystem if the -A flag was specified.

	if [[ $Op = Add ]]
	then
		startsrc -I -s $SUBSYS
		if [[ $? -eq 0 ]]
		then
			if [[ $OSname = "Linux" ]]
			then
				$SS_PATH/ctinitmgr -s $SUBSYS
			fi
		else
			exit 1
		fi
	fi

	;;

# start the subsystem 

start )
	startsrc -I -s $SUBSYS
	if [[ $? -eq 0 ]]
	then
		if [[ $OSname = "Linux" ]]
		then
			$SS_PATH/ctinitmgr -s $SUBSYS
		fi
	else
		exit 1
	fi

	;;

# stop the subsystem 

stop | stopall )
	# Stop Resource Managers if required

	if [[ $Op = stopall ]]
	then
		# get process IDs of all resource managers

		list=$(LC_ALL=C lssrc -g ${RMGRP} 2> /dev/null | grep "active" | \
			sed -n -e "$PARSE_SRC_PIDS" | tr '\n' ',')

		if [[ -n "${list}" ]]
		then
			wait_for_first
			stopsrc -c -g $RMGRP
		fi
	fi

	# Only stop subsystem if it is running

	state=$(LC_ALL=C lssrc -s "$SUBSYS" | sed "$PARSE_SRC_STATE")
	if [[ -n "$state" && "$state" = "active" ]]
	then
		wait_for_first
		stopsrc -s $SUBSYS -c
		if [[ $? -eq 0 ]]
		then
			if [[ $OSname = "Linux" ]]
			then
				$SS_PATH/ctinitmgr -k $SUBSYS
			fi
		else
			exit 1
		fi
	fi

	;;

# Delete all elements of the subsystem

delete )
	# Ensure subsystem is stopped 

	state=$(LC_ALL=C lssrc -s "$SUBSYS" | sed "$PARSE_SRC_STATE")
	if [[ -n "$state" && "$state" = "active" ]]
	then
		$CTMSG rmcctrl ct_rmc.cat EMSGG_Subsystem_Must_Be_Stopped \
				$CMD $SUBSYS
		exit 1
	fi

	rmssys -s $SUBSYS >/dev/null		# take subsystem out of SRC

	if [[ $OSname = "AIX" ]]
	then
		# remove the entry from inittab

		rmitab $SUBSYS 2> /dev/null
	fi

	if [[ $OSname = "Linux" ]]
	then
		# remove the symbolic links from /etc/rc.d/rc*.d
		$SS_PATH/ctinitmgr -d $SUBSYS
	fi

	# remove CDB and related files

	rm -f $CFGDIR/${CDBBASE}*

	# remove remote port enable file

	rm -f $START_PORT_FILE

	;;


# set client/server message policy

setmsgpolicy )
	case $MsgPolicy in
		R | E | D ) ;;
		* ) $CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
			exit 1 ;;
	esac

	rm -f $MSG_POLICY_FILE
	rmcsetmsgpolicy -s $SUBSYS -a $MsgPolicy
	if [[ $? -ne 0 ]]
	then
		exit 1
	fi
	print $MsgPolicy > $MSG_POLICY_FILE
	chmod 440 $MSG_POLICY_FILE

	;;


# set daemon-to-daemon message policy

setdmsgpolicy )
	case $MsgPolicy in
		R | E | D ) ;;
		* ) $CTMSG rmcctrl ct_rmc.cat INFOMsg_rmcctrl_Usage_E $CMD
			exit 1 ;;
	esac

	rm -f $DMSG_POLICY_FILE
	print $MsgPolicy > $DMSG_POLICY_FILE
	chmod 440 $DMSG_POLICY_FILE

	;;


# enable remote client connections

startport | delaystartport )
	rm -f $START_PORT_FILE
	touch $START_PORT_FILE
	chmod 440 $START_PORT_FILE

	if [[ $Op = startport ]]
	then
		rmcstartport -s $SUBSYS
		if [[ $? -ne 0 ]]
		then
			exit 1
		fi
	fi

	;;


# disable remote client connections

stopport | delaystopport)
	rm -f $START_PORT_FILE

	if [[ $Op = stopport ]]
	then
		rmcstopport -s $SUBSYS
		if [[ $? -ne 0 ]]
		then
			exit 1
		fi
	fi

	;;


# stop all RMC subsystems and wait for them to die

stopwait )

	# determine if there are any active subsystems

	ACTIVESUBSYS=$(active_subsys)

	if [ ${ACTIVESUBSYS} = y ]
	then
		# stop the subsystems

		wait_for_first
		stopsrc -c -g ${RMGRP} > /dev/null 2>&1
		stopsrc -c -g ${SUBSYSGRP} > /dev/null 2>&1

		# set loop limits

		(( i = ${WAITLIMIT} ))
		(( j = ${QUIECELIMIT} ))

		while (( $i > 0 && $j > 0 ))
		do
			# give the subsystems a chance to terminate

			sleep 2

			# see if any still alive

			ACTIVESUBSYS=$(active_subsys)

			if [ ${ACTIVESUBSYS} = y ]
			then
				# stop again
				stopsrc -c -g ${RMGRP} > /dev/null 2>&1
				stopsrc -c -g ${SUBSYSGRP} > /dev/null 2>&1

				# reset quiece time
				(( j = ${QUIECELIMIT} ))
			else
				(( j = $j - 2 ))
			fi
			(( i = $i - 2 ))
		done

		# check if the subsystems wouldn't die

		if [ ${ACTIVESUBSYS} = y ]
		then
			exit 2
		fi
	fi

	;;

# set message timeout in timeout option file
set_topt )

	timeout_option MSG_TIMEOUT $TimeOptArg
	;;

# set start timeout in timeout option file
set_uopt )

	timeout_option START_TIMEOUT $TimeOptArg
	;;

# set 1st command timeout in timeout option file
set_vopt )

	timeout_option CMD_TIMEOUT $TimeOptArg
	;;

# set 1st command threshold in timeout option file
set_wopt )

	timeout_option CMD_THRESHOLD $TimeOptArg
	;;

# enable "first cmd timeout for authenticated user" in timeout option file
set_xopt )

	timeout_option CMD_AUTHENT_ENABLE set
	;;

# remove message timeout from timeout option file (RMC uses default)
reset_topt )

	timeout_option MSG_TIMEOUT
	;;

# remove start timeout from timeout option file (RMC uses default)
reset_uopt )

	timeout_option START_TIMEOUT
	;;

# remove 1st command timeout from timeout option file (RMC uses default)
reset_vopt )

	timeout_option CMD_TIMEOUT
	;;

# remove 1st command threshold from timeout option file (RMC uses default)
reset_wopt )

	timeout_option CMD_THRESHOLD
	;;

# disable "first cmd timeout for authenticated user" in timeout option file
# this is the default
reset_xopt )

	timeout_option CMD_AUTHENT_ENABLE
	;;

esac

exit 0
