#!/bin/ksh -p
#
# ident "@(#)utprodinfo.ksh	1.12 04/10/19 SMI"
#
# Copyright 2003-2004 Sun Microsystems, Inc.  All rights reserved.
#


PATH=/bin:/usr/bin:/sbin:/usr/sbin
PROG=${0##*/}
ERROR_PREF="${PROG}:"

typeset MAPPEDLIST=""
typeset SEDLIST=""
typeset multiParam=true
#DEBUG="set -x"	# uncomment this line to turn on debugging

#
# Usage - prints the usage message
# $1 - the exit code
Usage() {
	typeset OUT=""

	if [[ $1 -ne 0 ]]; then
		OUT="-u2"
	fi
	print ${OUT} "
	${PROG}

	${PROG} -h

	${PROG} -t partial | installed | complete <pkgname>

	${PROG} -r <pkgname>

	${PROG} -p <pkgname> [ <param> ... ]

	- Supported parameters:
		${Param[@]}

	"

	exit $1
}

#
# setOP - makes sure that only one option is specified.
#
setOP() {
	if [[ -z "$OPMODE" ]]; then
		OPMODE=$1
	elif [[ "$OPMODE" = "$1" ]]; then
		print -u2 "only one instance of -${1} is allowed"
		Usage 1
	else
		print -u2 "conflicting options -${OPMODE} and -${1}"
		Usage 1
	fi
}

#
# defines the mapping for the parameters names.
# We can't use associative Array because ksh on Solaris is too old.
# NOTE 1: the order of the parameters listed in the array is critical
# in order for the Linux output to match the Solaris output.
# NOTE 2: MAXParam should be the number of parameters + 1.
#
# Parameter options for the command line
set -A Param
# Mapped parameter name for the Solaris packaging utility
set -A SunOS_Mapped_Param
# Sed script required to manipulate the output
set -A SunOS_Mapped_Sed
# Mapped parameter query format for the Linux packaging utility
set -A Linux_Mapped_Param
# Maximum number of parameters allowed
typeset -i MAXParam=1

# --- BASEDIR - basedirectory where the product is installed. Ex: /opt
Param[${MAXParam}]="BASEDIR"
SunOS_Mapped_Param[${MAXParam}]="BASEDIR"
Linux_Mapped_Param[${MAXParam}]="%{INSTALLPREFIX}"
let MAXParam+=1
# --- VERSION - version number with the build info.  Ex: 2.0_37.b
Param[${MAXParam}]="VERSION"
SunOS_Mapped_Param[${MAXParam}]="VERSION"
SunOS_Mapped_Sed[${MAXParam}]="s/\([0-9]\{1,\}\.[0-9]\{1,\}_[0-9]\{1,2\}\.\{0,1\}[a-z]\{0,1\}\),.*/\1/"
Linux_Mapped_Param[${MAXParam}]="%{VERSION}_%{RELEASE}"
let MAXParam+=1
# --- PSTAMP - product timestamp
Param[${MAXParam}]="PSTAMP"
SunOS_Mapped_Param[${MAXParam}]="PSTAMP"
Linux_Mapped_Param[${MAXParam}]="%{BUILDTIME:date}"
let MAXParam+=1
# --- NAME - description of the package.
Param[${MAXParam}]="NAME"
SunOS_Mapped_Param[${MAXParam}]="NAME"
Linux_Mapped_Param[${MAXParam}]="%{SUMMARY}"
let MAXParam+=1
# --- PRODVERS - product version without the build info.  Ex: 2.0
Param[${MAXParam}]="PRODVERS"
SunOS_Mapped_Param[${MAXParam}]="SUNW_PRODVERS"
Linux_Mapped_Param[${MAXParam}]="%{VERSION}"
let MAXParam+=1
# --- PKGNAME - package name. Ex: SUNWuto
Param[${MAXParam}]="PKGNAME"
SunOS_Mapped_Param[${MAXParam}]="PKGINST"
Linux_Mapped_Param[${MAXParam}]="%{NAME}"
let MAXParam+=1
# --- INSTDATE - date the package is installed on the system.
Param[${MAXParam}]="INSTDATE"
SunOS_Mapped_Param[${MAXParam}]="INSTDATE"
Linux_Mapped_Param[${MAXParam}]="%{INSTALLTIME:date}"
let MAXParam+=1
# --- PATCHLIST - list of patches installed for this package.
Param[${MAXParam}]="PATCHLIST"
SunOS_Mapped_Param[${MAXParam}]="PATCHLIST"
Linux_Mapped_Param[${MAXParam}]=""
let MAXParam+=1


###########################################################
#                                                         #
#     Common routines used by both platforms.		  #
#                                                         #
###########################################################

#
# addParameter - adds the specified parameter to the MAPPEDLIST.
# This list is used as an argument to the packaging utilities. 
# $1 - index number to the parameter array
# $2 - multiple parameters flag (Linux only).  It's true if there is more
#	than one parameter is specified by the user.  This is used
#	mainly for Linux so that it does not add the key into the
#	mapped list.
#
addParameter() {
	$DEBUG
	if [[ ${PREFIX} = "SunOS" ]]; then
		if [[ -z "${MAPPEDLIST}" ]]; then
			MAPPEDLIST="${SunOS_Mapped_Param[${1}]}"
		else
			MAPPEDLIST="$MAPPEDLIST ${SunOS_Mapped_Param[${1}]}"
		fi
		if [[ -n "${SunOS_Mapped_Sed[${1}]}" ]]; then
			# add value manipulation sed script
			if ${multiParam}; then
				SEDLIST="${SEDLIST} -e /^${SunOS_Mapped_Param[${1}]}=/${SunOS_Mapped_Sed[${1}]}"
			else
				SEDLIST="${SEDLIST} -e ${SunOS_Mapped_Sed[${1}]}"
			fi
		fi
		if [[ ${SunOS_Mapped_Param[${1}]} != ${Param[${1}]} ]]; then
			# add key name manipulation sed script
			SEDLIST="${SEDLIST} -e s/^${SunOS_Mapped_Param[${1}]}=/${Param[${1}]}=/"
		fi
	else
		if [[ -n "${Linux_Mapped_Param[${1}]}" ]]; then
			if ${2}; then
				MAPPEDLIST="${MAPPEDLIST}${Param[${1}]}=${Linux_Mapped_Param[${1}]}\\n"
			else
				MAPPEDLIST="${Linux_Mapped_Param[${1}]}\\n"
			fi
		fi
	fi
}


#
# buildParamList - builds the list of mapped parameters to be extracted
# $* - list of parameters
#
# Returns
# 0 if valid parameters found
# 1 otherwise.
#
buildParamList() {
	$DEBUG
	typeset -i idx=1
	typeset found
	typeset -i paramCount=0

	if [[ $# -eq 0 ]]; then
		# return all parameters
		while [[ ${idx} -lt ${MAXParam} ]]; do
			addParameter ${idx} ${multiParam}
			let idx=idx+1
		done
		return 0
	fi

	# look up the specified parameters.  If not in the matching list,
	# just drop the parameter.
	if [[ $# -eq 1 ]]; then
		# only one parameter was specified, so the key is not
		# required.  Only return the value.
		multiParam=false
	fi
	while [[ $# -ne 0 ]]; do
		idx=1
		found=false
		while [[ ${idx} -lt ${MAXParam} ]]; do
			if [[ ${Param[${idx}]} != "$1" ]]; then
				let idx=idx+1
				continue
			fi
			# found a match
			addParameter ${idx} ${multiParam}
			found=true
			let paramCount=paramCount+1
			break
		done
		# if ! ${found}; then
			# we don't support the parameter specified
			# just ignore it.  We may change this in the
			# future
			# :
		# fi
		shift 1
	done

	if [[ $paramCount -eq 0 ]]; then
		# no valid parameter specified
		return 1
	fi
	return 0
}


###########################################################
#                                                         #
#     Solaris version routines are defined here.          #
#                                                         #
###########################################################

#
# dispAll - displays the name and description for all the SunRay packages
# installed.
#
SunOS_dispAll() {
	$DEBUG
	pkginfo -c sunray | sed "s/^[^ 	]*[ 	][ 	]*//"
	return $?
}

#
# dispParams - displays the parameter information in key-value form.
# $* - parameter names.  List all parameters if omitted.
#
# Returns:
# 1 if package not installed
# 0 otherwise.  This includes the case when no valid parameters found.
#
SunOS_dispParams() {
	$DEBUG
	if ! ${PREFIX}_testPkg installed $PKGNAME; then
		# package not installed;
		print -u2 "${ERROR_PREF} package $PKGNAME not installed"
		return 1
	fi
	buildParamList "$@"
	if [[ $? -eq 1 ]]; then
		# found no params, just return
		return 0
	fi
	if ${multiParam}; then
		pkgparam -v $PKGNAME ${MAPPEDLIST} | \
			sed -e "s/='\(.*\)'$/=\1/" ${SEDLIST}
	else
		pkgparam $PKGNAME ${MAPPEDLIST} | \
			sed -e "s/='\(.*\)'$/=\1/" ${SEDLIST}
	fi
	return $?
}

#
# testPkg - test the condition specified on the package.
# $1 - test condition
# $2 - package name
#
SunOS_testPkg() {
	$DEBUG
	if [[ $# -ne 2 ]]; then
		return 1
	fi
	case $1 in
	"installed")	# package installed, could be either partial or complete
		pkginfo -q $2
		return $?;;
	"partial")	# package partially installed
		pkginfo -q -p $2 2> /dev/null
		return $?;;
	"complete")	# package completely installed
		if pkginfo -q $2 && ! pkginfo -q -p $2 2> /dev/null; then
			return 0
		fi
		return 1;;
	esac

	# invalid test condition
	print -u2 "${ERROR_PREF} invalid test operation \"$1\"."
	return 1
}


###########################################################
#                                                         #
#     Linux version routines are defined here.            #
#                                                         #
###########################################################

#
# dispAll - displays the name and description for all the SunRay packages
# installed.
#
Linux_dispAll() {
	$DEBUG
	# NOTE: must sort first so that we can return the exit code from grep
	rpm -q -a --queryformat "%-14{NAME} %{SUMMARY}\n" | \
	    (export LC_ALL=C; sort -u) | grep "Sun Ray"
	return $?
}

#
# dispParams - displays the parameter information in key-value form.
# $1 - package name
# $* - parameter names.  List all parameters if omitted.
#
Linux_dispParams() {
	$DEBUG
	if ! ${PREFIX}_testPkg installed $PKGNAME; then
		# package not installed;
		print -u2 "${ERROR_PREF} package $PKGNAME not installed"
		return 1
	fi

	buildParamList "$@"
	if [[ $? -eq 1 ]]; then
		# found no params, just return
		return 0
	fi
	rpm -q --queryformat ${MAPPEDLIST} $PKGNAME 2>/dev/null
	return 0
}


#
# testPkg - test the condition specified on the package.
# $1 - test condition
# $2 - package name
#
Linux_testPkg() {
	$DEBUG
	if [[ $# -ne 2 ]]; then
		return 1
	fi
	case $1 in
	"installed")	# package installed, could be either partial or complete
		rpm -q --quiet $2 > /dev/null 2>&1
		return $?;;
	"partial")	# package partially installed
		#
		# rpm does not understand the concept of partially installed packages.
		# So, for now, we always return 1 (ie. false) since it can never be
		# partially installed packages.
		#
		return 1;;
	"complete")	# package completely installed
		rpm -V --quiet $2 > /dev/null 2>&1
		return $?;;
	esac

	# invalid test condition
	print -u2 "${ERROR_PREF} invalid test operation \"$1\"."
	return 1
}


PREFIX=`uname -s`
if [[ -z "$PREFIX" ]]; then
	# undefined OS
	print -u2 "${ERROR_PREF} unable to determince the OS running on this system."
	exit 1
fi

OPMODE=""
SUBOP=""
PKGNAME=""

while getopts "hrt:p" c
do
	case $c in
	h)	setOP "h";;
	r)	setOP "r";;
	t)	setOP "t"
		SUBOP=$OPTARG;;
	p)	setOP "p";;
	*)	print -u2 "${ERROR_PREF} Invalid option."
		Usage 1;;
	esac
done

shift `expr $OPTIND - 1`

case ${OPMODE} in
"" | h)	# operations that do no require any extra argument
	if [[ $# -gt 0 ]]; then
		print -u2 "${ERROR_PREF} extra arguments found"
		print -u2 "\tArguments: $*"
		Usage 1
	fi
	case ${OPMODE} in
	"")	# display name and description for all packages
		${PREFIX}_dispAll;;
	h)	# print usage
		Usage 0;;
	esac;;
t | r)	# operations that require one extra argument
	if [[ $# -ne 1 ]]; then
		if [[ $# -gt 1 ]]; then
			print -u2 "${ERROR_PREF} only one argument is allowed."
			print -u2 "\tArguments: $*"
		else
			print -u2 "${ERROR_PREF} missing package name."
		fi
		Usage 1
	fi
	PKGNAME="$*"
	case ${OPMODE} in
	r)	# display basedir info
		${PREFIX}_dispParams "BASEDIR";;
	t)	# test for condition
		${PREFIX}_testPkg $SUBOP $PKGNAME;;
	esac;;
p)	# this operation requires packagename but the parameters are optional
	if [[ $# -lt 1 ]]; then
		print -u2 "${ERROR_PREF} missing package name."
		Usage 1
	fi
	PKGNAME="$1"
	shift 1
	${PREFIX}_dispParams "$@";;
esac

exit $?

