#!/bin/ksh 
#set -x
#
# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
# SUN PROPRIETARY/CONFIDENTIAL 
# Use is subject to license terms.
#

# This string is here for the 'version' command:
# It gets sed'ed in at build-time:
# @(#)RELEASE VERSION Forte Developer 7 Performance Analyzer 7.0 Patch 111705-03 2002/09/24

# Product and J2SE Validation script 

# Orion does not want the default location check
default_loc_warning="off"

# Orion won't check for V9 patches
V9patches="yes"

# Expected changes needed before FCS of FEE:
#  FIXUP: Will need to require latest libC patch, all platforms

# The J2SE version required by this product
version_needed="1.4"
version_ok="1.3.1"

# Solaris install locations for J2SE
solaris_loc="/usr/j2se"
default_loc="${solaris_loc}"

##########################################################################
# NOTE: These are the required patches, and may not be the latest patches.
#       Sunsolve will probably not have these specific patches available for
#       download, and the newer revs (which should be fine) may require
#       additional patches that are not in this list.
#       This list of patches may not be completely contained, i.e. these
#       patches may require additional patches not in this list. This
#       should be ok, in that this is a validation and not a patch installation
#       script, in theory all we need to do is check for the patches we
#       require and we need not verify that the complete patch tree is
#       on the system.
#	If a patch we wish to install has a newer rev on the system, then
#	that patch is satisfied by this newer rev patch.
#	If a patch has been made obsolete by some other patch on the system
#	then that patch is also considered satisfied by the other patch.
##########################################################################
#
# Patches needed for 5.7 and 5.8

# Should match the patch list file for the product, e.g. for FEE:
#  http://dpweb.eng.sun.com/set/misc/docs/common/installation/j2se_patch_order.txt

# i386/5.7 ...
collect_intel_57_patches=""
collect_intel_57_patches="${collect_intel_57_patches} 107545-03" # fsck
collect_intel_57_patches="${collect_intel_57_patches} 106542-18" # Kernel
collect_intel_57_patches="${collect_intel_57_patches} 106981-19" # libthread
collect_intel_57_patches="${collect_intel_57_patches} 108245-03" # libaio
intel_57_patches=""
intel_57_patches="${intel_57_patches} 106951-17" # Linker (Janus needs -17)
intel_57_patches="${intel_57_patches} 106328-13" # libC32bit
intel_57_patches="${intel_57_patches} 107545-03" # fsck
intel_57_patches="${intel_57_patches} 106542-18" # Kernel (Lint needs -19+?)
intel_57_patches="${intel_57_patches} 106981-19" # libthread
intel_57_patches="${intel_57_patches} 108377-29" # Xsun
intel_57_patches="${intel_57_patches} 107657-06" # libXt
intel_57_patches="${intel_57_patches} 107082-43" # Motif
intel_57_patches="${intel_57_patches} 107703-09" # CDE/dtsession
intel_57_patches="${intel_57_patches} 108375-05" # CDE/widget
intel_57_patches="${intel_57_patches} 107227-18" # CDE/dtwm
intel_57_patches="${intel_57_patches} 108245-03" # libaio
intel_57_patches="${intel_57_patches} 106749-04" # make/sccs
intel_57_patches="${intel_57_patches} 107637-08" # Xinput

# i386/5.8 ...
collect_intel_58_patches=""
collect_intel_58_patches="${collect_intel_58_patches} 108529-13" # Kernel
collect_intel_58_patches="${collect_intel_58_patches} 108828-18" # lwp/libthread
intel_58_patches=""
intel_58_patches="${intel_58_patches} 109148-14" # Linker (Janus needs -14)
intel_58_patches="${intel_58_patches} 108436-06" # libC32bit
intel_58_patches="${intel_58_patches} 108529-13" # Kernel
intel_58_patches="${intel_58_patches} 108653-34" # Xserver
intel_58_patches="${intel_58_patches} 108922-13" # CDE/dtwm
intel_58_patches="${intel_58_patches} 108941-40" # Motif
intel_58_patches="${intel_58_patches} 108774-12" # Xinput
intel_58_patches="${intel_58_patches} 109608-01" # stdlib_iso
intel_58_patches="${intel_58_patches} 108990-01" # Accounting
intel_58_patches="${intel_58_patches} 108828-18" # lwp/libthread

# sparc/5.7 ...
#
#                   libC64bit assembler
collect_sparc_57_patches=""
collect_sparc_57_patches="${collect_sparc_57_patches} 107544-03" # fsck
collect_sparc_57_patches="${collect_sparc_57_patches} 106541-18" # Kernel
collect_sparc_57_patches="${collect_sparc_57_patches} 106980-18" # libthread
collect_sparc_57_patches="${collect_sparc_57_patches} 108244-03" # libaio
sparc_57v9_patches=""
sparc_57_patches=""
sparc_57_patches="${sparc_57_patches} 106950-17" # Linker (Janus needs -17)
sparc_57_patches="${sparc_57_patches} 106327-13" # libC32bit
sparc_57v9_patches="${sparc_57v9_patches} 106300-14" # libC64bit
sparc_57_patches="${sparc_57_patches} 107544-03" # fsck
sparc_57_patches="${sparc_57_patches} 106541-18" # Kernel (Lint needs -19+?)
sparc_57_patches="${sparc_57_patches} 106980-18" # libthread
sparc_57_patches="${sparc_57_patches} 108376-33" # Xsun
sparc_57_patches="${sparc_57_patches} 107656-07" # libXt
sparc_57_patches="${sparc_57_patches} 107081-43" # Motif
sparc_57_patches="${sparc_57_patches} 107636-08" # Xinput
sparc_57_patches="${sparc_57_patches} 107702-09" # CDE/dtsession
sparc_57_patches="${sparc_57_patches} 108374-05" # CDE/widget
sparc_57_patches="${sparc_57_patches} 107226-18" # CDE/dtwm
sparc_57_patches="${sparc_57_patches} 108244-03" # libaio
sparc_57_patches="${sparc_57_patches} 106748-04" # make/sccs

sparc_57v9_patches="${sparc_57v9_patches} 107058-01" # Assembler

# sparc/5.8 ...
collect_sparc_58_patches=""
collect_sparc_58_patches="${collect_sparc_58_patches} 108528-13" # Kernel
collect_sparc_58_patches="${collect_sparc_58_patches} 108827-17" # lwp/libthread
sparc_58_patches=""
sparc_58v9_patches=""
sparc_58_patches="${sparc_58_patches} 109147-14" # Linker (Janus needs -14)
sparc_58_patches="${sparc_58_patches} 108434-06" # libC32bit
sparc_58v9_patches="${sparc_58v9_patches} 108435-06" # libC64bit
sparc_58_patches="${sparc_58_patches} 108528-13" # Kernel
sparc_58_patches="${sparc_58_patches} 108652-37" # Xserver 
sparc_58_patches="${sparc_58_patches} 108921-13" # CDE/dtwm
sparc_58_patches="${sparc_58_patches} 108940-40" # Motif
sparc_58_patches="${sparc_58_patches} 108773-12" # Xinput
sparc_58_patches="${sparc_58_patches} 109607-01" # stdlib_iso
sparc_58_patches="${sparc_58_patches} 108827-17" # lwp/libthread
sparc_58_patches="${sparc_58_patches} 108989-01" # Accounting

##########################################################################

# System commands used (don't rely on search paths)
HOSTNAME=/usr/bin/hostname
RM=/usr/bin/rm
CAT=/usr/bin/cat
TTY=/usr/bin/tty
XDPYINFO=/usr/openwin/bin/xdpyinfo
DTERROR=/usr/dt/bin/dterror.ds
UNAME=/usr/bin/uname
DTDSPMSG=/usr/dt/bin/dtdspmsg
DIRNAME=/usr/bin/dirname
CUT=/usr/bin/cut
SED=/usr/bin/sed
SORT=/usr/bin/sort
UNIQ=/usr/bin/uniq
EXPR=/usr/bin/expr
GREP=/usr/bin/grep
SHOWREV=/usr/bin/showrev
TOUCH=/usr/bin/touch
CHMOD=/usr/bin/chmod
BASENAME=/usr/bin/basename
ISALIST=/usr/bin/isalist
SLEEP=/usr/bin/sleep

# Name of this script (aka "perftools_validate" last time it got named)
scriptname="`${BASENAME} $0`"

# Location of script
scriptdir1="`${DIRNAME} $0`"
scriptdir="`cd ${scriptdir1} && pwd`"
if [ -d ${scriptdir1}/../READMEs ] ; then
    readmedir="`cd ${scriptdir1}/../READMEs && pwd`"
else
    readmedir="/opt/SUNWspro/prod/READMEs"
fi

# The website to get patches/J2SE
website="http://access1.sun.com/forte"

# Cache file
cache_file=/tmp/${scriptname}_ok.1.39
patch_check="yes"
# Buffering file
bufferfile=/tmp/${scriptname}_message_buffer.$$
${RM} -f ${bufferfile}

# Exit status for this script
exit_status=0  

# List of missing patches
missing_patches=""

# Obsolete list
obsolete_list=""
obsolete_base_list=""

# Make recommendation
make_recommendation="no"

# Java version
javaversion=""

# File that will contain showrev -p output
sys_patches=/tmp/.${scriptname}_showrev.$$

# Sunos of this machine
sunos="`${UNAME} -r`"

# Hostname of this machine
hostname="`${HOSTNAME}`"

##########################################################################
#
# Usage
#
Usage()
{
    echo "${scriptname}: Validates that the system/J2SE can run the Performance Tools"
    echo " " 
    echo "USAGE: ${scriptname} [-c] [-j path] [-J java] [-q] [-b] [-f] [-h] [-d] [-D] [-9]"
    echo "      -c            Collect only, also don't check default loc of J2SE"
    echo "      -j path       J2SE install location, check it"
    echo "      -J java       Java startup, check it"
    echo "      -q            Quiet mode, if system ok, say nothing"
    echo "      -p N          Pause for N seconds after issuing warnings"
    echo "      -b            Buffer up messages and send all at once"
    echo "      -f            Bypass the cache"
    echo "      -h            Print this help message"
    echo "      -d            Use dt"
    echo "      -D            Debug mode, script gets really noisy"
    echo "      -9            Check for V9 patches if it makes sense"
    echo " Exit status:"
    echo "    0 - ok"
    echo "    1 - warnings, not fatal to run J2SE"
    echo "    2 - bad J2SE, or missing patches, do not run"
    echo "    3 - internal error, contact support"
}

# 
# Internal error
#
InternalError()
{
    DumpBuffer
    echo "INTERNAL ERROR: $1"
    Usage
    exit 3
}

Debugmessage()
{
    if [ "${debugmode}" = "on" ] ; then
        echo "DEBUG: $1"
    fi
}

SetExitStatus()
{
    if [ ${exit_status} != 2 ] ; then
	exit_status=$1
    fi
}

#
# Sending message to console
#

Console()
{
    message="$1"
    if [ "${use_dt}" = "no" ] ; then
	echo "${message}"
    else
	${DTERROR} "${message}" "The Performance Tools" 'Continue'
    fi
}

#
# Dump buffer load of messages
#
DumpBuffer()
{
    if [ "${buffering}" = "on" ] ; then
	if [ -s ${bufferfile} ] ; then
	    Console "`${CAT} ${bufferfile}`"
	    ${RM} -f ${bufferfile}
	fi
    fi
}

#
# L10N Message translation utility
#

Message()
{
  # Message() - display message from ${scriptname}.cat
  #   $1 - message id
  #   $2 - fallback message text

  if [ "${buffering}" = "on" ] ; then
      if [ -x $DTDSPMSG ]; then
	    $DTDSPMSG -s 18 analyzer.cat $1 "$2" "$3" "$4" "$5" "$6" >> ${bufferfile}
      else
	    printf "$2" "$3" "$4" "$5" "$6" >> ${bufferfile}
      fi
      if [ "${use_dt}" = "yes" ] ; then
	    printf '\\n' >> ${bufferfile}
      fi
  else
      if [ -x $DTDSPMSG ]; then
	    $DTDSPMSG -s 18 analyzer.cat $1 "$2" "$3" "$4" "$5" "$6"
      else
	    printf "$2" "$3" "$4" "$5" "$6"
      fi
  fi
}

#
# Messages used
#

Recommendation()
{
   Message1text="NOTE: You can download and install the J2SE[tm] related Solaris[tm] patches from %s.\n" 
    Message 1 "${Message1text}" "${website}"
}

NotSupported()
{
    Message2text="ERROR: The J2SE[tm] %s found at %s cannot be used by the Performance tools. J2SE[tm] %s is recommended.\n"
    Message 2 "${Message2text}" "${javaversion}" "${javabin}" "${version_needed}"
    make_recommendation="yes"
    SetExitStatus 2
}

NotAvailable()
{
    Message3text="ERROR: No J2SE[tm] was found at %s.\n"
    Message 3 "${Message3text}" "${javabin}"
    make_recommendation="yes"
    SetExitStatus 2
}

NotNormal()
{
    Message4text="WARNING: The recommended default install location for J2SE[tm] %s is %s, not %s.\n"
    Message 4 "${Message4text}" "${version_needed}" "${default_loc}" "${javapath}"
    SetExitStatus 1
}

MissingPatches()
{
    Message5text="ERROR: The following required %s patches have not been installed on system \"%s\": %s\n"
    Message 5 "${Message5text}" "${sunos}" "${hostname}" "${missing_patches}"
    make_recommendation="yes"
    SetExitStatus 2
}

Validated()
{
    if [ ${quietmode} = "off" ] ; then
        Message6text="NOTE: SunOS %s system \"%s\" is correctly patched and set up for use with the Performance tools.\n"
        Message 6  "${Message6text}" "${sunos}" "${hostname}"
    fi
}

Unsupported()
{
    Message7text="ERROR: SunOS %s is not supported by the Performance tools.\n"
    Message 7 "${Message7text}" "${sunos}"
    SetExitStatus 2
}

##########################################################################
# Get obsolete patch list
GetObsoleteList()
{
    Debugmessage "Looking for obsolete patches"
    raw_obsolete_list="`${GREP} 'Obsoletes:' ${sys_patches} | ${SED} 's/.*Obsoletes:\([\ \	,0-9-]*\).*/\1/' | ${SED} -e 's/,/ /g'`"
    for i in ${raw_obsolete_list} END ; do
	if [ "${i}" = "END" ] ; then
	   break;
	fi
        for x in ${obsolete_list} END ; do
	    if [ "${x}" = "${i}" ] ; then
		break;
	    fi
	done
	if [ "${x}" != "${i}" ] ; then
	    obsolete_list="${obsolete_list} $i"
	fi
    done
    if [ "${obsolete_list}" != "" ] ; then
	obsolete_base_list="`echo ${obsolete_list} | ${SED} 's/\([1-9][0-9][0-9][0-9][0-9][0-9]\)-[0-9][0-9]/\1/g'`"
        Debugmessage "Obsolete base list: ${obsolete_base_list}"
    fi
    Debugmessage "Obsolete list: ${obsolete_list}"
}

##########################################################################
# See if a specific patch is on the system
CheckPatch() 
{
    foundpatch=""
    p=$1
    
    # See if patch is in the obsolete list
    Debugmessage "Looking for patch $p"
    base="`echo $p | ${SED} 's/\([1-9][0-9][0-9][0-9][0-9][0-9]\)-[0-9][0-9]/\1/'`"
    rev="`echo $p | ${SED} 's/[1-9][0-9][0-9][0-9][0-9][0-9]-\([0-9][0-9]\)/\1/'`"
    if [ "${obsolete_base_list}" != "" ] ; then
	for obase in ${obsolete_base_list} ; do
	    if [ "${base}" = "${obase}" ] ; then
		Debugmessage "Checking base patch ${base} for obsoleteness"
		orev=`echo "${obsolete_list}" | ${SED} "s/.*${base}-\([0-9][0-9]\).*/\1/"`
		Debugmessage "rev=${rev}, orev=${orev}"
		if [ `${EXPR} ${rev} '<=' ${orev}` = '1' ] ; then
		    Debugmessage "Found patch $i to be obsolete, making $p obsolete"
		    return
		fi
	    fi
	done
    fi

    all=`${GREP} "Patch: $base" $sys_patches`
    Debugmessage "Base of patch is ${base}, rev is ${rev}"
    if [ "$all" != "" ] ; then
        revs=`echo "$all" | ${SED} 's/^Patch: [1-9][0-9][0-9][0-9][0-9][0-9]-\([0-9][0-9]\).*$/\1/' | ${SORT} | ${UNIQ}`
        Debugmessage "Found the following revs: ${revs}"
	for r in $revs ; do
	    if [ `${EXPR} $rev '<=' $r` = '1' ] ; then
		foundpatch="$base-$r"
                Debugmessage "Found patch $p in form of $base-$r"
		break
	    fi
	done
    fi
    if [ "$foundpatch" = "" ] ; then
	Debugmessage "Missing patch $p"
        missing_patches="${missing_patches} ${p}"
    fi
}

# Function that checks all the patches
CheckAllPatches() # sunos sparc_patches intel_patches
{
    # Get obsolete list
    GetObsoleteList

    sunos="$1"
    arch="`${UNAME} -p`"
    if [ "${arch}" = sparc ] ; then
	patches="$2"
    else
	patches="$3"
    fi
    Debugmessage "Looking for ${arch} ${sunos} patches ${patches}"
    for i in ${patches} ; do
	CheckPatch $i
    done
}

# Get the version of java at javabin
GetJavaVersion()
{
    Debugmessage "Looking for version of Java at ${javabin}"
    if [ -f ${javabin} ] ; then
	javaversion=`${javabin} -version 2>&1 | ${GREP} 'java version' | ${SED} -e 's/.*\"\([1-9]\.[0-9\.]*\).*/\1/'`
	Debugmessage "Got version ${javaversion} from `${javabin} -version 2>&1 | ${GREP} 'java version'`"
    fi
}

##########################################################################

# l10n update this
#

NLSPATH="${scriptdir}/locale/%L/%N:${scriptdir}/../lib/locale/%L/LC_MESSAGES/%N:${NLSPATH}"
export NLSPATH

# Default values
quietmode="off"
buffering="off"
use_dt="no"

# If standard input is NOT a terminal, then we assume no console? Use popup.
${TTY} -s
if [ $? -ne 0 ] ; then
    use_dt="yes"
fi

javapath=""
javabin=""
collectmode="off"
debugmode="off"
forcemode="off"
psecs=""

# Parse the options supplied
while getopts bcdDfhj:J:qp:9 option
do
  case $option in
      # -c
      c) collectmode="on";;
      # -d
      d) use_dt="yes";;
      # -D
      D) debugmode="on";;
      # -f
      f) forcemode="on";;
      # -j path
      j) javapath="$OPTARG";;
      # -J javabin
      J) javabin="$OPTARG";;
      # -p N
      p) psecs="$OPTARG";;
      # -q
      q) quietmode="on";;
      # -9
      9) V9patches="yes";;
      # -b
      b) buffering="on";;
      # -h
      h) Usage
	 exit 0;;
      # Unknown
      \?) InternalError "Unknown option";;
    esac
done
shift `${EXPR} $OPTIND - 1`
if [ "$*" != "" ] ; then
    InternalError "Illegal input on command line: $*"
fi

# If using popup, make sure display is valid
if [ "${use_dt}" = "yes" ] ; then
    ${XDPYINFO} > /dev/null 2>&1 
    if [ $? -ne 0 ] ; then
	use_dt="no"
    else
        buffering="on"
    fi
fi

# The collect option may change the patch list
if [ "${collectmode}" = "on" ] ; then
    default_loc_warning="off"
    # Skip java check unless -j options seen
    if [ "${javapath}" = "" -a "${javabin}" = "" ] ; then
	# Just check collector patches
	Debugmessage "Changing patch list for collect"
        intel_57_patches="${collect_intel_57_patches}"
        intel_58_patches="${collect_intel_58_patches}"
	sparc_57v9_patches=""
	sparc_58v9_patches=""
        sparc_57_patches="${collect_sparc_57_patches}"
        sparc_58_patches="${collect_sparc_58_patches}"
    fi
else
    # Use default javapath  if not set
    if [ "${javapath}" = "" ] ; then
	javapath="${default_loc}"
    fi
fi

# Set javabin if javapath is set but javabin was not
if [ "${javapath}" != "" -a "${javabin}" = "" ] ; then
    javabin="${javapath}/bin/java"
fi

# If debugging mode is on, say what was requested
Debugmessage "quietmode=${quietmode}"
Debugmessage "collectmode=${collectmode}"
Debugmessage "debugmode=${debugmode}"
Debugmessage "forcemode=${forcemode}"
Debugmessage "javapath=${javapath}"
Debugmessage "javabin=${javabin}"

# Check system version first
if [ "${sunos}" = "5.9" ] ; then
    Debugmessage "${sunos} is ok"
elif [ "${sunos}" = "5.8" ] ; then
    Debugmessage "${sunos} is ok"
elif [ "${sunos}" = "5.7" ] ; then
    echo "Nothing to do yet" > /dev/null
else
    Unsupported
    javapath=""
    javabin=""
    patch_check="no"
fi

# If not your normal javapath, say so
if [ "${default_loc_warning}" = "on" -a "${javapath}" != "" -a "${javapath}" != "${default_loc}" ] ; then
    NotNormal
fi

# If we have a java to run, we check the java version
if [ "${javabin}" != "" ] ; then

    # Get the version of java being used
    GetJavaVersion
    Debugmessage "Found version ${javaversion} from ${javabin}"

    # Check J2SE itself
    if [ "${javaversion}" = "" ] ; then
	NotAvailable
    elif [ "${javaversion}" != "${version_ok}"  -a \
           "${javaversion}" != "${version_needed}" ] ; then
	minorno="`echo ${javaversion} | ${CUT} -f2 -d'.' `"
        Debugmessage "Found that minor version is ${minorno}"
	if [    "${minorno}" = "" 		\
	     -o "${minorno}" = 1		\
	     -o "${minorno}" = 2  		\
	     -o "${minorno}" = 3 ] ; then
	    NotSupported
	fi
    fi
fi

# If cache file doesn't exist, do the checks
if [ "${patch_check}" = "yes" ] ; then
    if [ "${forcemode}" = "on" -o ! -f ${cache_file} ] ; then

	# Remove v9 patches
	if [ "${V9patches}" = "no" -o "`${ISALIST} | ${GREP} sparcv9`" = "" ] ; then
	    sparc_57v9_patches=""
	    sparc_58v9_patches=""
	fi

	# Check the Solaris patches
	${RM} -f ${sys_patches}
	if [ "${sunos}" = "5.9" ] ; then
	    echo "Nothing to do yet" > /dev/null
	elif [ "${sunos}" = "5.8" ] ; then
	    ${SHOWREV} -p > ${sys_patches}
	    CheckAllPatches ${sunos} \
		"${sparc_58_patches} ${sparc_58v9_patches}" "${intel_58_patches}"
	elif [ "${sunos}" = "5.7" ] ; then
	    ${SHOWREV} -p > ${sys_patches}
	    CheckAllPatches ${sunos} \
		"${sparc_57_patches} ${sparc_57v9_patches}" "${intel_57_patches}"
	fi
	${RM} -f ${sys_patches}
	
	# Check to see if there were missing patches
	if [ "${missing_patches}" != "" ] ; then
	    MissingPatches
	fi

	# Touch cache file if we think it's ok
	if [ ${exit_status} = 0 ] ; then
	     ${TOUCH} -f ${cache_file}
	     ${CHMOD} a+rw ${cache_file}
	fi
    fi
fi

# If everything ok, issue validated message
if [ ${exit_status} = 0 ] ; then
    Validated
fi

# Make recommendation?
if [ "${make_recommendation}" = "yes" ] ; then
    Recommendation
fi

# If we are buffering up messages (-b option) dump the messages now
DumpBuffer

# If any warnings, wait a little to make sure they read them
if [ ${exit_status} != 0 ] ; then
    if [ "${psecs}" != "" ] ; then
        ${SLEEP} ${psecs}
    fi
fi
exit ${exit_status}
