#!/bin/ksh -p
#*******************************************************************************
#  Copyright 1998 Symbios Inc.  All Rights reserved.                           *
#  This file is confidential and a trade secret of Symbios Inc.  The receipt   *
#  or possession of this file does not convey any rights to reproduce or       *
#  disclose its contents or to manufacture, use, or sell anything it may       *
#  describe, in whole, or in part, without the specific written consent of     *
#  Symbios Inc.                                                                *
#*******************************************************************************

#*******************************************************************************
#
# NAME:		genscsiconf
# VERSION:	%version: 24 %
# UPDATE DATE:	%date_modified: Mon Jun 03 13:41:13 2002 %
# INSPECTED ON:
#
# CONTACTS:
#   Originator:
#   Owner:
#   Backup:
#   Updater:	%created_by:    shankara %
#
# DESCRIPTION:
#
#
# NOTES:
# This script updates /kernel/drv/sd.conf, AND THEN calls genfcaconf and symconf
# to update other /kernel/drv/xx.conf files.
#
# Script exit values are:
# 0 - no changes made (to any file)
# 1 - Errors occurred, no changes made 
# 2 - Changes were made  to at least one file (errors might have occurred along the way).
#
#
# REFERENCE:
# 1.  Source Code Integrity Measures
#
#
# CODING STANDARD WAIVERS:
#
#
#*******************************************************************************

#*******************************************************************************
# PROCEDURE:	 list_target_conf
#
# DESCRIPTION: uses awk to find all currently-bound targets in the JNI "fcaxxx"
# (or jnic) configuration files.
list_target_conf()
{
nawk '
/^#/ { next }
/target[0-9]+_(hba|wwpn)=/ {
	gsub ( "\"", "", $0)
	sub ( ";", " ;", $0)
	nf = split ( $0, fields )
	for (i = 1; i <= nf; i++ )
	{
		tgt = fields[i]
		if (match (tgt, "target[0-9]+_hba=") )
		{
			sub ( "target", "", tgt )
			sub ( "_hba.*$", "", tgt )
			printf "%s\n", tgt
		}
		if (match (tgt, "target[0-9]+_wwpn=") )
		{
			sub ( "^.*target", "", tgt )
			sub ( "_wwpn.*$", "", tgt )
			printf "%s\n", tgt
		}
	}
	next
}
'
}

#*******************************************************************************
# PROCEDURE:	 gen_sd_conf
#
# DESCRIPTION: Uses awk to spit out a new sd.conf file with all the LUNs I want.
# If any JNI WWN entries are found, they are eliminated. Therefore this should only 
# be used with the JNI 2.3 driver or greater.
gen_sd_conf()
{
RAID_FILE=$1
LUNS=$2
SDCONF=$3

nawk -v raid_file="$RAID_FILE" -v luns="$LUNS" -v sd_conf="$SDCONF" '
BEGIN {
	SUBSEP = ":"

	# parse raid_file to see which targets we should add.
	max_target=-1
	while ( (getline < raid_file) > 0 )
	{
		targets[$1]++
		if ( $1 > max_target)
		{
			max_target=$1
		}
	}
	close ( raid_file )

	state = "init"
	clrline = "FALSE"
}

{
	if ( state == "init" )
	{
		if ( match( sd_conf, "TRUE" ) )
		{
			if ( match( $0, "^# BEGIN RAID Manager .*" ) )
			{
				clrline="TRUE"
			}
			if ( match( clrline, "FALSE" ) )
			{
				print
			}
			next
		}
		if ( match( $0, "^# BEGIN RAID Manager wwn entries" ) )
		{
			state = "wwn"
			next
		}
		if ( match ( $0, "^# BEGIN RAID Manager additional lun entries" ) )
		{
			state = "luns"
			next
		}
		# clean up comments from an earlier genscsiconf version
		if ( match ( $0, "^# COMMENTED OUT by RAID Manager :" ) )
		{
			sub ("^# COMMENTED OUT by RAID Manager :", "", $0 )
		}
		if ( match ( $0, "^name=" ) )
		{
			state = "entry"
		}
		else
		{
			print
			next
		}
	}
	if ( state == "wwn" )
	{
		if ( match ( $0, "^# END RAID Manager wwn entries" ) )
		{
			state = "init"
		}
		next
	}
	if ( state == "luns" )
	{
		if ( match ( $0, "^# END RAID Manager additional lun entries" ) )
		{
			state = "init"
		}
		next
	}
	if ( state == "entry" )
	{
		# clean up comments from an earlier genscsiconf version
		if ( match ( $0, "^# COMMENTED OUT by RAID Manager :" ) )
		{
			sub ("^# COMMENTED OUT by RAID Manager :", "", $0 )
		}

		print

		# skip over other mid-entry comments.
		if ( match ( $0, "^#" ) )
		{
			next
		}

		# You want free-form entries? You got free-form entries!
		gsub ( "\"", "", $0)
		sub ( ";", " ;", $0)
		nf = split ( $0, fields )
		for (i = 1; i <= nf; i++ )
		{
			field = fields[i]
			if ( match ( field, "target=" ) )
			{
				split ( field, name_val, "=" )
				target = name_val[2]
			}
			if ( match ( field, "lun=" ) )
			{
				split ( field, name_val, "=" )
				lun = name_val[2]
			}
			if ( match ( field, ";" ) )
			{
				was_printed[target,lun] = 1
				state = "init"
			}
		}
		next
	}
}
END {
	if ( state != "init" )
	{
		printf "### ERROR parsing sd.conf. Unexpected end of file.\n"
	}
	printf "# BEGIN RAID Manager additional lun entries\n"
	printf "# DO NOT EDIT from BEGIN above to END below...\n"

	if ( match( sd_conf, "FALSE" ) )
	{
		for (tgt=0; tgt <= max_target; tgt++)
		{
			if (targets[tgt])
			{
				for (lun = 0; lun < luns ; lun ++)
				{
					if ( ! ( was_printed[tgt,lun] == 1 ) )
					{
						printf "name=\"sd\" class=\"scsi\" target=%s lun=%s;\n", tgt, lun
					}
				}
			}
		}
	}
	printf "# END RAID Manager additional lun entries\n"
}
'
}

#*******************************************************************************
# PROCEDURE:	 main
#
# DESCRIPTION: Generate sd.conf entries for array LUNs at IDs where arrays
# currently exist and at IDs where arrays might exist (hot add) OR at all IDs.
#
# SYNTAX:
#
#
# NOTES:
#
#
# RETURNS:
#
#

# G E N SCSI C O N F   M A I N   P R O C E D U R E

# First we set some defaults and stuff
RMPARAMS_FILE=/etc/raid/rmparams
QUICK=FALSE
USAGE="Usage:  $0 [ -v ]"
VERBOSE=FALSE
RAID_COMMENT="# COMMENTED OUT by RAID Manager :"
SENTINEL1="# BEGIN RAID Manager additional lun entries"
SENTINEL2="# END RAID Manager additional lun entries"
WARNING="# DO NOT EDIT from BEGIN above to END below..."

CONF_FILE=/kernel/drv/sd.conf
SSD_CONF_FILE=/kernel/drv/ssd.conf
GENFCACONF=/etc/raid/bin/genfcaconf
GENJNICONF=/etc/raid/bin/genjniconf
ADDINFO=/etc/raid/bin/add_config_info
SETDRV=/etc/raid/bin/set_drivers

PATH="/usr/bin:/usr/sbin:${PATH}"
export PATH

# Next we parse our command line args.
set -- `getopt qtv $* 2>/dev/null`
if [ $? != 0 ]
then
	echo $USAGE
	exit 1
fi
for i in $*
do
	case $i in
	-v) VERBOSE=TRUE; shift;;
	-q) QUICK=TRUE; shift;;
	-t) TEST=TRUE; shift;;
	--) shift; break;;
        esac
done

if [ "$VERBOSE" = "TRUE" ]
then
	set -x
fi

if [ "$TEST" = "TRUE" ]
then
	# Look for files in current directory
	RMPARAMS_FILE=rmparams
	CONF_FILE=sd.conf
	GENFCACONF=genfcaconf
	GENJNICONF=genjniconf
	ADDINFO=add_config_info
fi
$SETDRV

# Now we parse rmparams
MAXLUNS=`grep -v "^#" $RMPARAMS_FILE | grep System_MaxLunsPerController | cut -d= -f2`
MAXIDS=`grep -v "^#" $RMPARAMS_FILE | grep System_MaxSCSIid | cut -d= -f2`

RM_BOOT_HOME=`grep -v "^#" $RMPARAMS_FILE | grep System_RmBootHomeDirectory | cut -d= -f2`
RM_NAME_FILE=`grep -v "^#" $RMPARAMS_FILE | grep System_NamefileDirPath | cut -d= -f2`
NATIVE_DRIVERS=`grep -v "^#" $RMPARAMS_FILE | grep Rdac_NativeScsiDrivers`
IS_SD=`echo $NATIVE_DRIVERS | grep :sd`
if [ -z "${IS_SD}" ]
then
	CLRSDCNF="TRUE"
else
	CLRSDCNF="FALSE"
fi
if grep -v "^#" $RMPARAMS_FILE | grep -i "Rdac_HotAddDisabled.*=.*FALSE" >/dev/null 2>&1
then
	HOTADD_ALL="TRUE"
else
	HOTADD_ALL="FALSE"
fi
if grep -v "^#" $RMPARAMS_FILE | grep -i "Rdac_HotAddDisabled.*=.*PARTIAL" >/dev/null 2>&1
then
	RDAC_HOTADD_IDS=`grep -v "^#" $RMPARAMS_FILE | grep Rdac_HotAddIDs`
fi
if grep -v "^#" $RMPARAMS_FILE | grep -i "System_JaycorFibreWithSwitch.*=.*TRUE" >/dev/null 2>&1
then
	FIBRE_SWITCH="TRUE"
else
	FIBRE_SWITCH="FALSE"
fi

# Now we initialize some more stuff.
LAD=$RM_BOOT_HOME/lad
SYMCONF=$RM_BOOT_HOME/symconf

> /tmp/raid.$$
if [ "$QUICK" = "FALSE" ]
then
	# find out what is currently attached...
	$LAD -y >/tmp/genscsiconf.lad.$$

	# Huh! Sez right there in the man page lad _always_ returns 0. So this is useless code.
	# Well, some day, it _might_ report an error.
	if [ $? -ne 0 ]
	then
		echo "Error while creating RAID additions to SCSI .conf files: Unable to write /tmp/genscsiconf.lad.$$"
		exit 1
	fi

	# ...and dump it intp /tmp/raid.$$
	# but only lines that have "cxtx" numbers (ignore the "No RAID Devices" messge).
	grep "^c" /tmp/genscsiconf.lad.$$ |
	while read CTRL_INFO
	do
		ID=`echo $CTRL_INFO | cut -dt -f2 | cut -dd -f1`
		echo $ID >> /tmp/raid.$$
	done
fi

# find out what rmparams says we should configure...
ID=0
while [ $ID -le $MAXIDS ]
do
	if [ -n "${RDAC_HOTADD_IDS}" ]
	then
		HOT_ADD_DOID=`echo "$RDAC_HOTADD_IDS" | grep -c ":$ID:"`
	fi

	if [ "${HOTADD_ALL}" = "TRUE" ] || [ "${HOT_ADD_DOID}"  -gt 0 ]
	then
		# ...and dump it into /tmp/raid.$$
		echo $ID  >>/tmp/raid.$$
		if [ $? -ne 0 ]
		then
			echo "Error while creating RAID additions to sd.conf: Unable to write /tmp/raid.$$"
			exit 1
		fi
	fi
	ID=`expr ${ID} + 1`
done

# rv, in this case, means "Return Value"
rv=0

# Need to generate the new fcaw.conf (and/or fca-pci.conf, or jnic.conf) file here,
# to make sure it's up-to-date
# But note that genfcaconf should not be a mandatory file... 
if [ "$QUICK" = "FALSE" ]
then
	if [ -x $GENFCACONF ] 
	then
		$GENFCACONF
		fc_rv=$?
		if [ $fc_rv -gt $rv ]
		then
			rv=$fc_rv
		fi
	fi
	if [ -x $GENJNICONF ] 
	then
		$GENJNICONF
		fc_rv=$?
		if [ $fc_rv -gt $rv ]
		then
			rv=$fc_rv
		fi
	fi
fi

# Find out what fibre channel devices we should configure...
if [ "${FIBRE_SWITCH}" = "TRUE" ]
then
	for CONF in fca fcaw fca-pci jnic
	do
		if [ "$TEST" = "TRUE" ]
		then
	 		FCACONFFILE=$CONF.conf
		else
			FCACONFFILE=/kernel/drv/$CONF.conf
		fi

		if [ -f $FCACONFFILE ]
		then
			# ... and dump that to (you guessed it) /tmp/raid.$$
			list_target_conf < $FCACONFFILE >>/tmp/raid.$$
		fi
	done
fi

# Possibly generate a new ssd.conf file.
if [ -x $ADDINFO ]
then
        # Add retry parameters if the script to do so exists.
        $ADDINFO ssd < $SSD_CONF_FILE >/tmp/new_ssd.$$
        if grep -i "ERROR" /tmp/new_ssd.$$ >/dev/null 2>&1
        then
                # This is "shouldn't happen" code. We don't expect any problems updating
                # ssd.conf. So, don't abort the install if there is an error.
                echo "genscsiconf: error encountered while updating configuration files."
                echo "    You will have to update /kernel/drv/ssd.conf manually."
                echo "    The file /tmp/new_ssd.conf contains the changes you need to apply."
                echo "    Errors are marked with comments containing the word ERROR."
                mv /tmp/new_ssd.$$ /tmp/new_ssd.conf
        else
                mv /tmp/new_ssd.$$ $SSD_CONF_FILE
        fi
fi


# Now generate the new sd.conf file in /tmp by blending together old sd.conf and raid
if [ -x $ADDINFO ]
then
	# Add retry parameters if the script to do so exists.
	gen_sd_conf /tmp/raid.$$ $MAXLUNS $CLRSDCNF < $CONF_FILE | $ADDINFO sd >/tmp/new_sd.$$
else
	gen_sd_conf /tmp/raid.$$ $MAXLUNS $CLRSDCNF < $CONF_FILE >/tmp/new_sd.$$
fi

sd_rv=0
if grep -i "ERROR" /tmp/new_sd.$$ >/dev/null 2>&1
then
	echo "genscsiconf: error encountered while updating configuration files."
	echo "    You will have to update /kernel/drv/sd.conf manually."
	echo "    The file /tmp/new_sd.conf contains the changes you need to apply."
	echo "    lines beginning with ### ERROR need to be fixed."
	cp /tmp/new_sd.$$ /tmp/new_sd.conf
	sd_rv=1
else
	cmp -s /tmp/new_sd.$$ $CONF_FILE
	crv=$?
	if [ $crv -eq 0 ]
	then
		sd_rv=0
	elif [ $crv -eq 1 ]
	then
		cp /tmp/new_sd.$$ $CONF_FILE 2>/dev/null
		# Yeah, copy _can_ fail.
		if [ $? -eq 0 ]
		then
			# successfully changed sd.conf
			sd_rv=2
		else
			sd_rv=1
		fi
	else
		#rv > 1 from cmp indicates error.
		echo "Error while creating RAID additions to sd.conf: Unable to write $CONF_FILE"
		sd_rv=1
	fi
fi

if [ $sd_rv -gt $rv ]
then
	rv=$sd_rv
fi
if [ $rv -eq 1 ]
then
	echo "Error while creating RAID additions to sd.conf: Unable to write $CONF_FILE"
	exit 1
fi

rm -f /tmp/sd.conf.$$ /tmp/raid.sd.conf.$$ /tmp/genscsiconf.lad.$$ 2>/dev/null
rm -f /tmp/raid.$$  /tmp/new_sd.$$ 2>/dev/null


FILE=rdriver.conf
if [ "$TEST" = "TRUE" ]
then
	INPUT_FILE=$FILE
else
	INPUT_FILE=/kernel/drv/$FILE
fi
sc_rv=0

if [ "$QUICK" = "FALSE" ]
then
   if [ -x $SYMCONF -a -f $INPUT_FILE ]
   then
	OUTPUT_FILE=/tmp/${FILE}.$$
	$SYMCONF >$OUTPUT_FILE
	sc_err=$?
	if [ $sc_err -ne 0 ]
	then
		if [ $sc_err -eq 10 ]
		then
			echo "Warning: /kernel/drv/rdnexus.conf has run out of pseudo-busses."
			echo "Some disk array controllers may not be accessible."
			echo "View /tmp/symconf.err to see which entries are missing."
			# Now we gotta dump a warning to the rmlog, and possibly the system log.
			sys=`uname -n`
			datime=`date +%m/%e/%Y~%H:%M:%S`
			echo "${sys}~~Unknown~${datime}~90~Warning: /kernel/drv/rdnexus.conf has run out of pseudo-busses. Some disk array controllers may not be accessible. View the file /tmp/symconf.err to see which entries are missing.~0~FFFFFFFF~0~00000000~" >/tmp/logme.$$
			/etc/raid/bin/rmscript /tmp/logme.$$
			# .. and rmscript automatically deletes the file.
		else
			echo "Error: Unable to build /kernel/drv/rdriver.conf."
		fi
		sc_rv=$sc_err
	else
		cmp -s $INPUT_FILE $OUTPUT_FILE
		crv=$?
		if  [ $crv -eq 0 ]
		then
			sc_rv=0
		elif [ $crv -eq 1 ]
		then
			cp $OUTPUT_FILE $INPUT_FILE 2>/dev/null
			if [ $? -eq 0 ]
			then
				sc_rv=2
			else
				sc_rv=1
			fi
		else
			sc_rv=1
		fi
		rm -f $OUTPUT_FILE
	fi
   fi
fi

if [ $sc_rv -gt $rv ]
then
	rv=$sc_rv
fi

# So our return values are (let's be paranoid about this):
# 0: no errors, but sd.conf was not changed; reboot unnecessary.
# 1: errors occurred, sd.conf unchanged; reboot pointless (until you fix the errors).
# 2: sd.conf (or fcaxx.conf, or rdriver.conf) successfully changed; reboot needed.
# 10: we ran out of IDs somewhere (either in rdnexus or on the fibre channel)

exit $rv
