#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 1999,2019 
# 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 

# sccsid = "@(#)37   1.3   src/rsct/pts/pam/tools/hatstune.sh, topology.services, rsct_rady, rady2035a 11/12/15 16:45:58"

#########################################################################
#									#
# hatstune - script to tune the Topology Services Daemon tunables.	#
# Syntax:								#
#     hatstune [-f frequency] [-s sensitivity] [-p priority]		#
#              [-l log_length] [-m pin_object] [-r]			#
#     hatstune -d [-r]							#
#     hatstune -v							#
#     hatstune -h							#
#									#
# Value checking ("-v" option) can be performed on any SP node by any	#
# user. Value assignment ("-f", "-s", "-p", "-l", "-m", and "-d" 	#
# options) can only be run on the Control Workstation by users who have #
# root privilege. Refresh ("-r" option) needs root privilege due to 	#
# the use of "hatsctrl -r".						#
#									#
# "hatsctrl" changes HATS tunable default values also. Change default	#
# values in hatsctrl if anything changed in hatstune.			#
#									#
#########################################################################

print_message() {
    print -u2 "`${MSGCMD} $*`"
}

#########################################################################
#									#
# Function: chk_reuse							#
# Description: Check if an option is re-used. If it is, exit.		#
# Input parameter:							#
#     $1 : use-counter							#
#     $2 : option name e.g. -m						#
#									#
#########################################################################

chk_reuse()
{
    if (( ${1} > 0 ))
    then
	#print -u2 Option ${2} can not be re-used.
	print_message EMSG722 ${SCRIPT} ${2}
	exit 1
    fi
}

#########################################################################
#									#
# Function: chk_number							#
# Description: Check if the given argument is a valid decimal integer.	#
#     If it is a valid integer, check if it is inside valid range.	#
#     This function uses /usr/bin/tr to remove all numeric characters	#
#     in the given argument $1. If $1 is not empty, it must contain	#
#     non-numeric characters.						#
# Input parameter:							#
#     $1 : number to be checked						#
#     $2 : lower bound of valid range					#
#     $3 : upper bound of valid range					#
# Return value:								#
#	0 : if $1 is "default"						#
#	1 : if $1 is a valid decimal integer and $2 <= $1 <= $3.	#
#	2 : if $1 is a valid decimal integer and $1 < $2.		#
#	3 : if $1 is a valid decimal integer and $1 > $3.		#
#	4 : if $1 contains non-numeric characters 			#
#	5 : if $1 is an empty string.					#
# Bugs: 000123 is considered a valid decimal integer			#
#									#
#########################################################################

chk_number()
{
    # [ -z "${1}" ] matches only empty string ("").
    # [ -z "`echo ${1}`" ] matches blank strings of any length as well.
    if [ -n "`echo ${1}`" ]
    then
	if [[ "`echo $1 | tr '[:lower:]' '[:upper:]'`" = "DEFAULT" ]]
	then
	    # $1="default"
	    return 0
	else
	    if [ -z "`echo $1 | tr -d '[:digit:]'`" ]
	    then
		# Valid number. Check range.
		if (( $1 < $2 ))
		then
		    # Valid number. Out of range, too small
		    return 2
		else
		    if (( $1 > $3 ))
		    then
			# Valid number. Out of range, too large
			return 3
		    else
			# Valid number. In valid range
			return 1
		    fi
		fi
	    else
		# $1 contains non-numeric characters
		return 4
	    fi
	fi
    else
	# Blank or empty string
	return 5
    fi
}

#########################################################################
#                                                                       #
# Function: get_dce_credential                                          #
# Description: Use dsrvtgt to get certified DCE credentials as a        #
# service principal. The credentials cache file is created by DCE in    #
# /opt/dcelocal/var/security/creds. We use kdestroy later on to remove  #
# the credentials file. We will assume the identity of ssp/spbgroot     #
# service pricipal for admin access to SDR. See the SP security         #
# services configuration file /usr/lpp/ssp/config/spsec_defaults.       #
# Defect 48570.                                                         #
#                                                                       #
#########################################################################
get_dce_credential () {
    old_krb5=$KRB5CCNAME
    KRB5CCNAME=$(/usr/lpp/ssp/bin/dsrvtgt ssp/spbgroot)
    rc=$?
    if [[ $rc -ne 0 ]]; then
       	print_message EMSG749 ${SCRIPT} $rc
       	exit $rc
    fi
    export KRB5CCNAME
}

#########################################################################
#                                                                       #
# Function: destroy_dce_credential                                      #
# Description: Remove any DCE credentials file we may have obtained.    #
# Return KRB5CCNAME to original value. Defect 48570                     #
#                                                                       #
#########################################################################
destroy_dce_credential () {
    /bin/kdestroy >/dev/null 2>&1
    KRB5CCNAME=$old_krb5
    export KRB5CCNAME
}

#########################################################################
#									#
# mainline code								#
#									#
#########################################################################

#set -x

export PATH=/usr/bin:/usr/sbin:/usr/lpp/ssp/bin:/usr/lpp/ssp/install/bin:/opt/rsct/bin
export MSGMAPPATH="/opt/rsct/msgmaps"

SCRIPT=$(basename $0)		# name of subsystem group
HATSCTRL=/opt/rsct/bin/hatsctrl	# hatsctrl is used for refresh
MSGCMD="/opt/rsct/bin/hadspmsg hatstune hats.cat"
PRINTABLE_NULLSTR="\"''\""	# Null string acceptable by hadspmsg.

#
# Phase 0: initialize minimum, maximum, and default values for tunables.
#
#
# The default tunables are being set in hatsctrl also. The default
# tunables need to be changed in hatsctrl if they are changed in hatstune.
#
MIN_FREQ=1
MAX_FREQ=30
DEF_FREQ=1
MIN_SENS=4
MAX_SENS=40
DEF_SENS=4
MIN_PRIO=10
MAX_PRIO=80
DEF_PRIO=38
MIN_LOGL=2000
MAX_LOGL=1000000
DEF_LOGL=5000
DEF_MEMP="Text"

#
# Phase 1: Parse command line and check syntax.
# All error caught in this phase will cause the program to exit.
#

OPT_FREQ=0
OPT_SENS=0
OPT_PRIO=0
OPT_LOGL=0
OPT_MEMP=0
OPT_REFR=0
OPT_VALU=0
OPT_DEFA=0
OPT_HELP=0
PARM_FREQ_NET=""
PARM_FREQ_VAL=""
PARM_SENS_NET=""
PARM_SENS_VAL=""
PARM_MEMP=""
TUNE_TSCONFIG=0
TUNE_NETWORK=0
NUM_OPTS=0
ALL_NET_FREQ=0
ALL_NET_SENS=0

# ":f:s:p:l:m:rvdh"
while getopts ":f:s:p:l:m:rvdh" opt
do
    # The following "tr -d '[:space:]'" remove all space characters
    # including ' ', '\t'. This takes care of the extra space between
    # ',' and 'S' in the following option:
    # {hatstune -f "SPether:3, SPswitch:3"}. It also takes care of
    # {hatstune -l " "}.
    OPTARG=`echo ${OPTARG} | tr -d '[:space:]'`
    case $opt in
    f )	# Set frequency netname:value (in seconds)
	if (( ${OPT_DEFA} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -f can not coexist with options -d and -h.
	    print_message EMSG723 ${SCRIPT} "-f"
	    exit 1
	fi
	if [ -z "${OPTARG}" ]
	then
	    # A blank or empty string is not considered a regular extra option
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	fi
	# Add a ',' to protect ${OPTARG} from over parsing
	OPTARG="${OPTARG},"
	while [ -n "${OPTARG}" ]
	do
	    # Get the first parameter of ${OPTARG} up to ','.
	    OPTARG1=${OPTARG%%,*}
	    # Remove the first parameter from ${OPTARG}. (including ',')
	    OPTARG=${OPTARG#${OPTARG1},}
	    if [ -n "${OPTARG1}" ]
	    then
		# break NETNAME and OPTVAL by ":". 5 possible combinations are:
		# -f netname:value : NETNAME=netname, OPTVAL=value : Valid
		# -f netname:      : NETNAME=netname, OPTVAL=""    : Invalid
		# -f :value        : NETNAME=""     , OPTVAL=value : Valid
		# -f :             : NETNAME=""     , OPTVAL=""    : Invalid
		# -f value         : NETNAME=""     , OPTVAL=value : Valid
		OPTVAL=${OPTARG1#*:}
		OPTARG1=${OPTARG1%%${OPTVAL}}
		NETNAME=${OPTARG1%%:}

		chk_number "${OPTVAL}" "${MIN_FREQ}" "${MAX_FREQ}"
		case $? in
		0 )	# keyword "default"
		    if [ -z "${NETNAME}" ]
		    then
			# Check if default frequency has been defined.
			if (( ${ALL_NET_FREQ} > 0 ))
			then
			    #print -u2 Default frequency value is redefined
			    print_message EMSG730 ${SCRIPT}
			    exit 1
			fi
			(( ALL_NET_FREQ = ALL_NET_FREQ + 1 ))
			ALL_NET_FREQ_VAL=${DEF_FREQ}
			(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
		    else
			# Check if the netname has been defined.
			echo "${PARM_FREQ_NET}" | grep -w ${NETNAME}
			if (( $? == 0 ))
			then
			    #print -u2 Frequency value of network ${NETNAME} is redefined
			    print_message EMSG732 ${SCRIPT} ${NETNAME}
			    exit 1
			fi
			PARM_FREQ_NET="${PARM_FREQ_NET}${NETNAME} "
			PARM_FREQ_VAL="${PARM_FREQ_VAL}${DEF_FREQ},"
			(( TUNE_NETWORK = TUNE_NETWORK + 1 ))
			(( OPT_FREQ = OPT_FREQ + 1 ))
		    fi
		    ;;
		1 )	# Valid number
		    if [ -z "${NETNAME}" ]
		    then
			# Check if default frequency has been defined.
			if (( ${ALL_NET_FREQ} > 0 ))
			then
			    #print -u2 Default frequency value is redefined
			    print_message EMSG730 ${SCRIPT}
			    exit 1
			fi
			(( ALL_NET_FREQ = ALL_NET_FREQ + 1 ))
			ALL_NET_FREQ_VAL=${OPTVAL}
			(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
		    else
			# Check if the netname has been defined.
			echo "${PARM_FREQ_NET}" | grep -w ${NETNAME}
			if (( $? == 0 ))
			then
			    #print -u2 Frequency value of network ${NETNAME} is redefined
			    print_message EMSG732 ${SCRIPT} ${NETNAME}
			    exit 1
			fi
			PARM_FREQ_NET="${PARM_FREQ_NET}${NETNAME} "
			PARM_FREQ_VAL="${PARM_FREQ_VAL}${OPTVAL},"
			(( TUNE_NETWORK = TUNE_NETWORK + 1 ))
			(( OPT_FREQ = OPT_FREQ + 1 ))
		    fi
		    ;;
		2 )	# Value too small
		    #print -u2 Frequency value ${OPTVAL} is too small. Valid range is \[${MIN_FREQ}, ${MAX_FREQ}\]
		    print_message EMSG740 ${SCRIPT} ${OPTVAL} ${MIN_FREQ} ${MAX_FREQ}
		    exit 1
		    ;;
		3 )	# Value too large
		    #print -u2 Frequency value ${OPTVAL} is too large. Valid range is \[${MIN_FREQ}, ${MAX_FREQ}\]
		    print_message EMSG741 ${SCRIPT} ${OPTVAL} ${MIN_FREQ} ${MAX_FREQ}
		    exit 1
		    ;;
		4 )	# Invalid number
		    #print -u2 ${OPTVAL} is not a valid decimal number.
		    print_message EMSG728 ${SCRIPT} "${OPTVAL}"
		    exit 1
		    ;;
		5 )	# Blank or empty string
		    #print -u2 A valid decimal number is expected.
		    print_message EMSG729 ${SCRIPT}
		    exit 1
		    ;;
		esac
	    fi
	done
	;;
    s ) # Set sensitivity netname:value
	if (( ${OPT_DEFA} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -s can not coexist with options -d and -h.
	    print_message EMSG723 ${SCRIPT} "-s"
	    exit 1
	fi
	if [ -z "${OPTARG}" ]
	then
	    # "" " is not considered a regular extra option
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	fi
	# Add a ',' to protect ${OPTARG} from over parsing
	OPTARG="${OPTARG},"
	while [ -n "${OPTARG}" ]
	do
	    OPTARG1=${OPTARG%%,*}
	    OPTARG=${OPTARG#${OPTARG1},}
	    if [ -n "${OPTARG1}" ]
	    then
		# break NETNAME and OPTVAL by ":". 5 possible combinations are:
		# -s netname:value : NETNAME=netname, OPTVAL=value : Valid
		# -s netname:      : NETNAME=netname, OPTVAL=""    : Invalid
		# -s :value        : NETNAME=""     , OPTVAL=value : Valid
		# -s :             : NETNAME=""     , OPTVAL=""    : Invalid
		# -s value         : NETNAME=""     , OPTVAL=value : Valid
		OPTVAL=${OPTARG1#*:}
		OPTARG1=${OPTARG1%%${OPTVAL}}
		NETNAME=${OPTARG1%%:}
		
		chk_number "${OPTVAL}" "${MIN_SENS}" "${MAX_SENS}"
		case $? in
		0 )	# keyword "default"
		    if [ -z "${NETNAME}" ]
		    then
			# Check if default sensitivity has been defined.
			if (( ${ALL_NET_SENS} > 0 ))
			then
			    #print -u2 Default sensitivity value is redefined
			    print_message EMSG731 ${SCRIPT}
			    exit 1
			fi
			(( ALL_NET_SENS = ALL_NET_SENS + 1 ))
			ALL_NET_SENS_VAL=${DEF_SENS}
			(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
		    else
			# Check if the netname has been defined.
			echo "${PARM_SENS_NET}" | grep -w ${NETNAME}
			if (( $? == 0 ))
			then
			    #print -u2 Sensitivity value of network ${NETNAME} is redefined
			    print_message EMSG733 ${SCRIPT} ${NETNAME}
			    exit 1
			fi
			PARM_SENS_NET="${PARM_SENS_NET}${NETNAME} "
			PARM_SENS_VAL="${PARM_SENS_VAL}${DEF_SENS},"
			(( TUNE_NETWORK = TUNE_NETWORK + 1 ))
			(( OPT_SENS = OPT_SENS + 1 ))
		    fi
		    ;;
		1 )	# valid decimal integer
		    if [ -z "${NETNAME}" ]
		    then
			# Check if default sensitivity has been defined.
			if (( ${ALL_NET_SENS} > 0 ))
			then
			    #print -u2 Default sensitivity value is redefined
			    print_message EMSG731 ${SCRIPT}
			    exit 1
			fi
			(( ALL_NET_SENS = ALL_NET_SENS + 1 ))
			ALL_NET_SENS_VAL=${OPTVAL}
			(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
		    else
			# Check if the netname has been defined.
			echo "${PARM_SENS_NET}" | grep -w ${NETNAME}
			if (( $? == 0 ))
			then
			    #print -u2 Sensitivity value of network ${NETNAME} is redefined
			    print_message EMSG733 ${SCRIPT} ${NETNAME}
			    exit 1
			fi
			PARM_SENS_NET="${PARM_SENS_NET}${NETNAME} "
			PARM_SENS_VAL="${PARM_SENS_VAL}${OPTVAL},"
			(( TUNE_NETWORK = TUNE_NETWORK + 1 ))
			(( OPT_SENS = OPT_SENS + 1 ))
		    fi
		    ;;
		2 )	# Value too small
		    #print -u2 Sensitivity value ${OPTVAL} is too small. Valid range is \[${MIN_SENS}, ${MAX_SENS}\]
		    print_message EMSG742 ${SCRIPT} ${OPTVAL} ${MIN_SENS} ${MAX_SENS}
		    exit 1
		    ;;
		3 )
		    #print -u2 Sensitivity value ${OPTVAL} is too large. Valid range is \[${MIN_SENS}, ${MAX_SENS}\]
		    print_message EMSG743 ${SCRIPT} ${OPTVAL} ${MIN_SENS} ${MAX_SENS}
		    exit 1
		    ;;
		4 )	# invalid number
		    #print -u2 ${OPTVAL} is not a valid decimal number.
		    print_message EMSG728 ${SCRIPT} "${OPTVAL}"
		    exit 1
		    ;;
		5 )	# Blank or empty string
		    #print -u2 A valid decimal number is expected.
		    print_message EMSG729 ${SCRIPT}
		    exit 1
		    ;;
		esac
	    fi
	done
	;;
    p ) # Set fixed priority 
	chk_reuse ${OPT_PRIO} "-p"
	if (( ${OPT_DEFA} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -p can not coexist with options -d and -h.
	    print_message EMSG723 ${SCRIPT} "-p"
	    exit 1
	fi
	if [ -z "${OPTARG}" ]
	then
	    # A blank or empty string is not considered a regular extra option
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	fi
	chk_number "${OPTARG}" "${MIN_PRIO}" "${MAX_PRIO}"
	case $? in
	0 )	# keyword "default"
	    PARM_PRIO=${DEF_PRIO}
	    (( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	    (( OPT_PRIO = OPT_PRIO + 1 ))
	    ;;
	1 )	# Valid number
	    PARM_PRIO=${OPTARG}
	    (( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	    (( OPT_PRIO = OPT_PRIO + 1 ))
	    ;;
	2 )	# Value too small
	    # 0 is a special value to specify not running in fixed priority.
	    if (( ${OPTARG} == 0 ))
	    then
		PARM_PRIO=${OPTARG}
		(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
		(( OPT_PRIO = OPT_PRIO + 1 ))
	    else
		#print -u2 Priority value ${OPTARG} is too small. Valid range is \[${MIN_PRIO}, ${MAX_PRIO}\]
		print_message EMSG744 ${SCRIPT} ${OPTARG} ${MIN_PRIO} ${MAX_PRIO}
		exit 1
	    fi
	    ;;
	3 )	# Value too large
	    #print -u2 Priority value ${OPTARG} is too large. Valid range is \[${MIN_PRIO}, ${MAX_PRIO}\]
	    print_message EMSG745 ${SCRIPT} ${OPTARG} ${MIN_PRIO} ${MAX_PRIO}
	    exit 1
	    ;;
	4 )	# Invalid number
	    #print -u2 ${OPTARG} is not a valid decimal number.
	    print_message EMSG728 ${SCRIPT} "${OPTARG}"
	    exit 1
	    ;;
	5 )	# Blank or empty string
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	    ;;
	esac
	;;
    l ) # Set maximum log file length (in lines)
	chk_reuse ${OPT_LOGL} "-l"
	if (( ${OPT_DEFA} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -l can not coexist with options -d and -h.
	    print_message EMSG723 ${SCRIPT} "-l"
	    exit 1
	fi
	if [ -z "${OPTARG}" ]
	then
	    # A blank or empty string is not considered a regular extra option
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	fi
	chk_number "${OPTARG}" "${MIN_LOGL}" "${MAX_LOGL}"
	case $? in
	0 )	# Keyword "default"
	    PARM_LOGL=${DEF_LOGL}
	    (( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	    (( OPT_LOGL = OPT_LOGL + 1 ))
	    ;;
	1 )	# Valid number
	    PARM_LOGL=${OPTARG}
	    (( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	    (( OPT_LOGL = OPT_LOGL + 1 ))
	    ;;
	2 )	# Value too small
	    #print -u2 Maximum number of line in the log files ${OPTARG} is too small. Valid range is \[${MIN_LOGL}, ${MAX_LOGL}\]
	    print_message EMSG746 ${SCRIPT} ${OPTARG} ${MIN_LOGL} ${MAX_LOGL}
	    exit 1
	    ;;
	3 )	# Value too large
	    #print -u2 Maximum number of line in the log files ${OPTARG} is too small. Valid range is \[${MIN_LOGL}, ${MAX_LOGL}\]
	    print_message EMSG747 ${SCRIPT} ${OPTARG} ${MIN_LOGL} ${MAX_LOGL}
	    exit 1
	    ;;
	4 )
	    #print -u2 ${OPTARG} is not a valid decimal number.
	    print_message EMSG728 ${SCRIPT} "${OPTARG}"
	    exit 1
	    ;;
	5 )	# Blank or empty string
	    #print -u2 A valid decimal number is expected.
	    print_message EMSG729 ${SCRIPT}
	    exit 1
	    ;;
	esac
	;;
    m ) # Set Text, Proc, Data pinning
	chk_reuse ${OPT_MEMP} "-m"
	if (( ${OPT_DEFA} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -m can not coexist with options -d and -h.
	    print_message EMSG723 ${SCRIPT} "-m"
	    exit 1
	fi
	if [ -z "${OPTARG}" ]
	then
	    # A blank or empty string is not considered a regular extra option
	    #print -u2 Options -f, -s, -p, -l, and -m need an extra option.
	    print_message EMSG726 ${SCRIPT}
	    exit 1
	fi
	OPTVAL=`echo ${OPTARG} | tr '[:lower:]' '[:upper:]'`
	if [[ "${OPTVAL}" = "PROC" || "${OPTVAL}" = "TEXT" || \
	    "${OPTVAL}" = "DATA" || "${OPTVAL}" = "NONE" || \
	    "${OPTVAL}" = "DEFAULT" ]]
	then
	    case ${OPTVAL} in
	    "NONE" )	PARM_MEMP="None" ;;
	    "TEXT" )	PARM_MEMP="Text" ;;
	    "DATA" )	PARM_MEMP="Data" ;;
	    "PROC" )	PARM_MEMP="Proc" ;;
	    "DEFAULT" )	PARM_MEMP="${DEF_MEMP}" ;;
	    esac
	    (( OPT_MEMP = OPT_MEMP + 1 ))
	    (( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	else
	    #print -u2 \"${OPTARG}\" is not a valid object. Valid objects are None, Text, Data, Proc, and default.
	    print_message EMSG727 ${SCRIPT} "${OPTARG}"
	    exit 1
	fi
	;;
    r ) # Refresh
	chk_reuse ${OPT_REFR} "-r"
	(( OPT_REFR = OPT_REFR + 1 ))
	;;
    v ) # Show current values
	chk_reuse ${OPT_VALU} "-v"
	(( OPT_VALU = OPT_VALU + 1 ))
	;;
    d ) # Reset all values to default values
	chk_reuse ${OPT_DEFA} "-d"
	# Althought "-d" also set ${TUNE_NETWORK}, the above line has already
	# got rid of this posibility.
	# 
	if (( ${TUNE_TSCONFIG} + ${TUNE_NETWORK} + ${OPT_HELP} > 0 ))
	then
	    #print -u2 Option -d can not coexists with options -f, -s, -p, -l, -m, and -h.
	    print_message EMSG724 ${SCRIPT}
	    exit 1
	fi
	(( TUNE_TSCONFIG = TUNE_TSCONFIG + 1 ))
	(( TUNE_NETWORK = TUNE_NETWORK + 1 ))
	(( OPT_DEFA = OPT_DEFA + 1 ))
	;;
    h ) # Print help message
	chk_reuse ${OPT_HELP} "-h"
	if (( ${TUNE_TSCONFIG} + ${TUNE_NETWORK} > 0 ))
	then
	    #print -u2 Option -h can not coexists with options -f, -s, -p, -l, -m, and -d.
	    print_message EMSG725 ${SCRIPT}
	    exit 1
	fi
	(( OPT_HELP = OPT_HELP + 1 ))
	;;
    : ) # Missing extra options in options -f, -s, -p, -l, -m.
	#print -u2 Options -f, -s, -p, -l, and -m need an extra option.
	print_message EMSG726 ${SCRIPT}
	exit 1
	;;
    \? ) # Undefined options
	#print -u2 Option \"${opt}\" is not a valid option.
	print_message EMSG721 ${SCRIPT} "${OPTARG}"
	exit 1
	;;
    esac
    (( NUM_OPTS = NUM_OPTS + 1 ))
done

# Print help message if "-h" option or no option flag is specified.
# We'd like to execute all options in the last phase. However, we make
# an exception for "-h" and put it in phase 1. This exception allows
# "-h" to print out help message without any other software installed.
if (( ${NUM_OPTS} == 0 || ${OPT_HELP} > 0 ))
then
    #print -u2 Usage:
    print_message I_TUNE_Usage ${SCRIPT}
    # We do allow some options to coexist with "-h". e.g. "-v".
    # We do not exit here if these options are used.
    if (( ${NUM_OPTS} <= 1 ))
    then
	exit 0
    fi
fi

#
# Phase 2: Process options that need further checking
# Starting this phase, all commands are for SP environment.
# Check if the specified network names and required SDR resources exist.
#

# Check if SDR is working.
if [ -x /usr/lpp/ssp/bin/SDRGetObjects ]
then
    if (( `/usr/lpp/ssp/bin/SDRGetObjects -x Syspar 2> /dev/null | wc -l` == 0 ))
    then
	#print -u2 SDR subsystem is not working properly.
	print_message EMSG751 ${SCRIPT}
	exit 1
    fi
else
    #print -u2 PSSP command /usr/lpp/ssp/bin/SDRGetObjects is missing. Check if PSSP is installed properly.
    print_message EMSG750 ${SCRIPT} "/usr/lpp/ssp/bin/SDRGetObjects"
    exit 1

fi

# Changing tunable values must be performed on control workstation.
if [ -x /usr/lpp/ssp/install/bin/node_number ]
then
    NODE_NUMBER=`/usr/lpp/ssp/install/bin/node_number`
    if (( ${TUNE_TSCONFIG} + ${TUNE_NETWORK} > 0 && ${NODE_NUMBER} != 0 ))
    then
	#print -u2 HATS tunable values can only be changed on the control workstation.
	print_message EMSG755 ${SCRIPT}
	exit 1
    fi
else
    #print -u2 PSSP command /usr/lpp/ssp/install/bin/node_number is missing. Check if PSSP is installed properly.
    print_message EMSG750 ${SCRIPT} "/usr/lpp/ssp/install/bin/node_number"
    exit 1
fi

# SDR is up and running. We can query SDR classes
# TS_Config and Network

if (( ${TUNE_TSCONFIG} + ${OPT_VALU} > 0 ))
then
    TSCONFIG_VAL=`SDRGetObjects -x -d ',' TS_Config Frequency Sensitivity Run_FixPri FixPri_Value Log_Length Pinning 2> /dev/null`
    if (( $? == 0 ))
    then
	# The above SDRGetObjects should return 6 values in one line
	if (( `echo "${TSCONFIG_VAL}" | wc -l` == 0 ))
	then
	    if (( ${TUNE_TSCONFIG} != 0 ))
	    then
		# Missing TS_Config is not a problem for tuning.
		# We can create it if it is not there. However, we
		# can not create it until we got credential.
		TS_CONFIG_EXIST=0
	    else
		# Missing TS_Config is a problem for "-v" since we need to
		# report the values stored in TS_Config.
		#print -u2 Error retrieving SDR class TS_Config
		print_message EMSG754 ${SCRIPT}
		exit 1
	    fi
	else
	    TS_CONFIG_EXIST=1
	fi
    else
	#print -u2 Error retrieving SDR class TS_Config
	print_message EMSG754 ${SCRIPT}
	exit 1
    fi
fi

# Network specific tuning is applied to known networks only.
if (( ${TUNE_NETWORK} + ${OPT_VALU} > 0 ))
then
    KNOWN_NETS=`SDRGetObjects -x Network networkName`

    if (( ${OPT_FREQ} > 0 ))
    then
	for i in ${PARM_FREQ_NET}
	do
	    echo "${KNOWN_NETS}" | grep -w ${i}
	    if (( $? != 0 ))
	    then
		#print -u2 Network name ${i} is not defined.
		print_message EMSG748 ${SCRIPT} ${i}
		exit 1
	    fi
	done
    fi

    if (( ${OPT_SENS} > 0 ))
    then
	for i in ${PARM_SENS_NET}
	do
	    echo "${KNOWN_NETS}" | grep -w ${i}
	    if (( $? != 0 ))
	    then
		#print -u2 Network name ${i} is not defined.
		print_message EMSG748 ${SCRIPT} ${i}
		exit 1
	    fi
	done
    fi
fi

if (( ${OPT_REFR} > 0 ))
then
    # "-r" option requires root privilege.
    EFFECT_ID=`/usr/bin/id -un`
    if [[ "${EFFECT_ID}" != "root" ]]
    then
	#print -u2 "-r" option requires root privilege.
	print_message EMSG734 ${SCRIPT}
	exit 1
    fi
fi

#
# Phase 3 : Really update HATS tunables
# We try to minimize SDR access by grouping all changes in two SDR accesses:
# one to update TS_Config class, the other to update Network class.

# Credetential is needed for updating SDR.
# Note: destroy_dce_credential() must be called before exit() if credential
#       is not destroyed.
if (( ${TUNE_TSCONFIG} + ${TUNE_NETWORK} > 0 ))
then
    get_dce_credential
fi

# Changing TS_Config
if (( ${TUNE_TSCONFIG} > 0 ))
then
    if (( ${OPT_DEFA} > 0 ))
    then
	CMD_STR="Frequency=${DEF_FREQ} \
	    Sensitivity=${DEF_SENS} Run_FixPri=1 FixPri_Value=${DEF_PRIO} \
	    Log_Length=${DEF_LOGL} Pinning=${DEF_MEMP}"
    else
	CMD_STR=""
	if (( ${ALL_NET_FREQ} > 0 ))
	then
	    CMD_STR="${CMD_STR} Frequency=${ALL_NET_FREQ_VAL}"
	fi
	if (( ${ALL_NET_SENS} > 0 ))
	then
	    CMD_STR="${CMD_STR} Sensitivity=${ALL_NET_SENS_VAL}"
	fi
	if (( ${OPT_PRIO} > 0 ))
	then
	    if (( ${PARM_PRIO} != 0 ))
	    then
		CMD_STR="${CMD_STR} Run_FixPri=1 FixPri_Value=${PARM_PRIO}"
	    else
		CMD_STR="${CMD_STR} Run_FixPri=0"
	    fi
	fi
	if (( ${OPT_LOGL} > 0 ))
	then
	    CMD_STR="${CMD_STR} Log_Length=${PARM_LOGL}"
	fi
	if (( ${OPT_MEMP} > 0 ))
	then
	    CMD_STR="${CMD_STR} Pinning=${PARM_MEMP}"
	fi
    fi

    # Create TS_Config if it is not there
    if (( ${TS_CONFIG_EXIST} == 0 ))
    then
	SDRCreateObjects TS_Config \
	    Frequency=${DEF_FREQ} Sensitivity=${DEF_SENS} \
	    Run_FixPri=1 FixPri_Value=${DEF_PRIO} \
	    Log_Length=${DEF_LOGL} Pinning=${DEF_MEMP}
	if (( $? != 0 ))
	then
	    #print -u2 Error changing attribute values of SDR class TS_Config
	    print_message EMSG752 ${SCRIPT}
	    destroy_dce_credential
	    exit 1
	fi
    fi
    SDRChangeAttrValues TS_Config ${CMD_STR}
    if (( $? != 0 ))
    then
	#print -u2 Error changing attribute values of SDR class TS_Config
	print_message EMSG752 ${SCRIPT}
	destroy_dce_credential
	exit 1
    else
	#print -u2 The following HATS tunables are changed:
	print_message I_TUNE_ChgHead
	if (( ${OPT_DEFA} > 0 ))
	then
	    #print -u2 Default heart beat frequency is changed to ${DEF_FREQ}
	    print_message I_TUNE_ChgFreq ${DEF_FREQ}
	    #print -u2 Default heart beat sensitivity is changed to ${DEF_SENS}
	    print_message I_TUNE_ChgSens ${DEF_SENS}
	    #print -u2 Use fixed priority ${DEF_PRIO}
	    print_message I_TUNE_ChgPrio ${DEF_PRIO}
	    #print -u2 Maximum number of lines in log files is changed to ${DEF_LOGL}
	    print_message I_TUNE_ChgLogl ${DEF_LOGL}
	    #print -u2 Pinning ${DEF_MEMP} in real memory
	    print_message I_TUNE_ChgMemp ${DEF_MEMP}
	else
	    if (( ${ALL_NET_FREQ} > 0 ))
	    then
		#print -u2 Default heart beat frequency is changed to ${ALL_NET_FREQ_VAL}
		print_message I_TUNE_ChgFreq ${ALL_NET_FREQ_VAL}
	    fi
	    if (( ${ALL_NET_SENS} > 0 ))
	    then
		#print -u2 Default heart beat sensitivity is changed to ${ALL_NET_SENS_VAL}
		print_message I_TUNE_ChgSens ${ALL_NET_SENS_VAL}
	    fi
	    if (( ${OPT_PRIO} > 0 ))
	    then
		if (( ${PARM_PRIO} != 0 ))
		then
		    #print -u2 Use fixed priority ${PARM_PRIO}
		    print_message I_TUNE_ChgPrio ${PARM_PRIO}
		else
		    #print -u2 Use non-fixed priority 
		    print_message I_TUNE_ChgNfix   
		fi
	    fi
	    if (( ${OPT_LOGL} > 0 ))
	    then
		#print -u2 Maximum number of lines in log files is changed to ${PARM_LOGL}
		print_message I_TUNE_ChgLogl ${PARM_LOGL}
	    fi
	    if (( ${OPT_MEMP} > 0 ))
	    then
		#print -u2 Pinning ${PARM_MEMP} in real memory
		print_message I_TUNE_ChgMemp ${PARM_MEMP}
	    fi
	fi
    fi
fi

# Changing Network
if (( ${TUNE_NETWORK} > 0 ))
then
    if (( ${OPT_DEFA} > 0 ))
    then
	KNOWN_NETS=`SDRGetObjects -x Network networkName`
	if (( `echo "${KNOWN_NETS}" | wc -l` > 0 ))
	then
	    #print -u2 Changing heart beat frequency to %1$s and sensitivity to %2$s\n\ for the following networks:
	    print_message I_TUNE_ChgFreqSensNet ${DEF_FREQ} ${DEF_SENS} 
	    # Re-assign $KNOWN_NETS to put all network names in one line.
	    KNOWN_NETS=`echo ${KNOWN_NETS}`
	    FIRST_ONE=1
	    for i in ${KNOWN_NETS}
	    do
		SDRChangeAttrValues Network networkName==${i} \
		    hbInterval=${DEF_FREQ} hbTolerance=${DEF_SENS}
		if (( $? != 0 ))
		then
		    #print -u2 Error changing attribute values of SDR class Network
		    print_message EMSG752 ${SCRIPT} ${i}
		    destroy_dce_credential
		    exit 1
		else
		    ##print -u2  "        ${i}"
		    print_message I_TUNE_ChgNetName ${i}
		fi
	    done
	fi
    fi

    if (( ${OPT_FREQ} > 0 ))
    then
	#print -u2 chang network specific heart beat frequency:
	print_message I_TUNE_ChgFreqNet
	for i in ${PARM_FREQ_NET}
	do
	    OPTVAL=${PARM_FREQ_VAL%%,*}
	    PARM_FREQ_VAL=${PARM_FREQ_VAL#${OPTVAL},}
	    SDRChangeAttrValues Network networkName==${i} hbInterval=${OPTVAL}
	    if (( $? != 0 ))
	    then
		#print -u2 Error changing attribute values of SDR class Network
		print_message EMSG752 ${SCRIPT} ${i}
		destroy_dce_credential
		exit 1
	    else
		#print -u2 "    network ${i} is changed to ${OPTVAL}"
		print_message I_TUNE_ChgNetVal ${i} ${OPTVAL}
	    fi
	done
    fi

    if (( ${OPT_SENS} > 0 ))
    then
	#print -u2 chang network specific heart beat sensitivity:
	print_message I_TUNE_ChgSensNet
	for i in ${PARM_SENS_NET}
	do
	    OPTVAL=${PARM_SENS_VAL%%,*}
	    PARM_SENS_VAL=${PARM_SENS_VAL#${OPTVAL},}
	    SDRChangeAttrValues Network networkName==${i} hbTolerance=${OPTVAL}
	    if (( $? != 0 ))
	    then
		#print -u2 Error changing attribute values of SDR class Network for network ${i}
		print_message EMSG753 ${SCRIPT} ${i}
		destroy_dce_credential
		exit 1
	    else
		#print -u2 "    network ${i} is changed to ${OPTVAL}"
		print_message I_TUNE_ChgNetVal ${i} ${OPTVAL}
	    fi
	done
    fi
fi

# Destroy credential
if (( ${TUNE_TSCONFIG} + ${TUNE_NETWORK} > 0 ))
then
    destroy_dce_credential
fi

# Do HATS refresh for "-r" option
if (( ${OPT_REFR} > 0 ))
then
    # No success/fail messages here since hatsctrl produces these messages.
    ${HATSCTRL} -r
    rc=$?
    if (( $rc != 0 ))
    then
       exit $rc
    fi
fi

# -v option
# -v option uses values from SDR. Need to check if the values are 
# non-blank before printing.
# Note : "[ -z "`echo $STR`" ]" returns TRUE if $STR is empty or blank 
# strings of any length.
if (( ${OPT_VALU} > 0 ))
then
    # We need to get SDR here in case the values are changed by tuning options.
    TSCONFIG_VAL=`SDRGetObjects -x -d ',' TS_Config Frequency Sensitivity Run_FixPri FixPri_Value Log_Length Pinning 2> /dev/null`
    if (( $? == 0 ))
    then
	# The above SDRGetObjects should return 6 values in one line
	if (( `echo "${TSCONFIG_VAL}" | wc -l` == 0 ))
	then
	    #print -u2 Error retrieving SDR class TS_Config
	    print_message EMSG754 ${SCRIPT}
	    exit 1
	else
	    #print -u2 Current HATS tunable values:
	    print_message I_TUNE_ValHead
	    OPTVAL=${TSCONFIG_VAL%%,*}
	    TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=${PRINTABLE_NULLSTR};
	    fi
	    #print -u2 Frequency: ${OPTVAL}
	    print_message I_TUNE_ValFreq ${OPTVAL}
	    OPTVAL=${TSCONFIG_VAL%%,*}
	    TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=${PRINTABLE_NULLSTR};
	    fi
	    #print -u2 Sensitivity: ${OPTVAL}
	    print_message I_TUNE_ValSens ${OPTVAL}
	    OPTVAL=${TSCONFIG_VAL%%,*}
	    TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=0;		# Null value is considered 0.
	    fi
	    if (( ${OPTVAL} > 0 ))
	    then
		OPTVAL=${TSCONFIG_VAL%%,*}
		TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
		if [ -z "`echo ${OPTVAL}`" ]
		then
		    OPTVAL=${PRINTABLE_NULLSTR};
		fi
		#print -u2 Running fixed priority: ${OPTVAL}
		print_message I_TUNE_ValFPri ${OPTVAL}
	    else
		OPTVAL=${TSCONFIG_VAL%%,*}
		TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
		if [ -z "`echo ${OPTVAL}`" ]
		then
		    # When Run_FixPri=0 and FixPri_Value="", the output looks
		    # like the following if OPTVAL=$PRINTABLE_NULLSTR:
		    # Running non-fixed priority. Priority value  ignored.
		    #                                           ^^(empty string)
		    # 
		    # Print double quotes "" instead of nothing and the output
		    # looks like:
		    # Running non-fixed priority. Priority value "" ignored.
		    OPTVAL='\"\"';
		fi
		#print -u2 Running non-fixed priority. Priority value ${OPTVAL} ignored
		print_message I_TUNE_ValNFix ${OPTVAL}
	    fi
	    OPTVAL=${TSCONFIG_VAL%%,*}
	    TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=${PRINTABLE_NULLSTR};
	    fi
	    #print -u2 Maximum number of lines in log file: ${OPTVAL}
	    print_message I_TUNE_ValLogl ${OPTVAL}
	    OPTVAL=${TSCONFIG_VAL%%,*}
	    TSCONFIG_VAL=${TSCONFIG_VAL#${OPTVAL},}
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=${PRINTABLE_NULLSTR};
	    fi
	    #print -u2 Pinning in real memory: ${OPTVAL}
	    print_message I_TUNE_ValMemp ${OPTVAL}
	fi
    else
	#print -u2 Error retrieving SDR class TS_Config
	print_message EMSG754 ${SCRIPT}
	exit 1
    fi

    for i in ${KNOWN_NETS}
    do
	SDRGetObjects -x Network networkName==${i} hbInterval hbTolerance | \
	    read OPTVAL OPTVAL2
	if (( $? == 0 ))
	then
	    if [ -z "`echo ${OPTVAL}`" ]
	    then
		OPTVAL=${PRINTABLE_NULLSTR};
	    fi
	    if [ -z "`echo ${OPTVAL2}`}" ]
	    then
		OPTVAL2=${PRINTABLE_NULLSTR};
	    fi
	    #print -u "    Network: ${i}	Frequency: ${OPTVAL}	Sensibility: ${OPTVAL2}"
	    print_message I_TUNE_ValNet ${i} "${OPTVAL}" "${OPTVAL2}"
	fi
    done
fi
 

exit 0