return to PRS Technologies website
###############################################################################
#!/usr/bin/ksh
#$Revision: 4.17 $
#
# Note from Peter Schmidt - on 5/23/2001
# To run this, login as "root" and run this script with no arguments.
# It creates a file named "[hostname].fs" in the /tmp directory.
#
# A note to 9.X users: If problems occur with the shell invocation, change the
# first line from /usr/bin/sh to /usr/bin/posix/sh";
#
# Modified: Nov 21 09:51:08 MST 1997 - kc
#
# 3.01 Sep 20, 1998 - ba
# Added kd's fix
# made y2k support fix.
#
# 3.02 Sep 30, 1998 - ba
# Get "Architecture" data from product
# if not with fileset.
# Made assumption that the correct "product" set
# is the "product" set immediately before "filset" set.
# with swlist commands.
#
# 3.03 Sep 14, 1999 - fs
# Initialize patch_state prior to processing each output
# line of swlist.
#
# 3.04 March 1, 2000 - fs
# Due to patch_state not being totally reliable as an
# indicator that a patch has been superseded, a
# check on the attribute superseded_by has been added.
# Also, the naming convention for patch filesets changed
# for 11.X. Code was added to filter out patch filesets
# from the product and fileset listing, which were being
# added for 11.X systems due to this inconsistency.
#
# 3.05 Nov 21, 2000 - sms
# Attempt to consolidate the code base and extend functionality
# for ipatch. 9.X functionality removed. All prompt user information
# except for handle removed.
# Limit size of output fields to field width (fixes Java-JRE revision).
scriptversion="A.03.05"
export PATH=/usr/bin:/usr/sbin:/sbin
unalias `alias | cut -f1 -d"="`
HOMEDIR="$HOME"
if [ -z "$HOMEDIR" ]
then
HOMEDIR="/tmp"
fi
set -o nounset
BATCH=false
CPM=false
COP=false
# default directory in which to create files
PSIDIR=/tmp
# name of info file
INFOFILE=PTRACK.info
# default batch mode to off
BATCH=false
#set up script name for subsequent use in messages
SCRIPT_NAME=$0
#header/trailer tags
header_tag=TH
trailer_tag=TT
# current directory
CWD=`pwd`
#================================================================
# Function to get user response.
# Input : $1 - prompt
# $2 - "E" list of Enumerated choices $4, $5, [$6]
# "X" same as above; do not show user choices
# "R" range of numeric choices $4 - $5; do not show user choices
# "Y" accept y,n,yes,no or any case-insensitive combination
# $3 - "N" // accepted to cancel, non-fatal
# "NX" same as above, do not show // option
# "F" // accepted to exit on confirmation, fatal
# "FX" same as above, do not show // option
# "X" // not accepted
# $4 - valid response
# $5 - valid response
# $6 - optional valid response
# Output : user_selection
#================================================================
get_selection () {
get_selection_prompt=$1
resp_type=$2
slash_ok=$3
resp1=$4
resp2=$5
if [ $# -gt 5 ]
then
resp3="$6"
else
resp3=
fi
while [ 1 = 1 ]
do
user_selection=""
#show prompt
echo "$get_selection_prompt \c"
#show enumerated choices, as desired
if [ $resp_type = "E" ]
then
echo "($resp1/$resp2\c"
if [ $resp3 ]
then
echo "/$resp3\c"
fi
echo ") \c"
fi
if [ $slash_ok = "N" ] || [ $slash_ok = "F" ]
then
echo "or // to cancel \c"
fi
# echo ":\c"
read user_selection
if [ "$user_selection" = "" ]
then
continue
fi
if [ "$user_selection" = "//" ]
then
if [ $slash_ok = "N" ] || [ $slash_ok = "NX" ]
then
#// accepted to cancel input
user_selection=""
return
elif [ $slash_ok = "F" ] || [ $slash_ok = "FX" ]
then
#user can exit, or continue with input
echo ""
echo "Cancelling now will discard any changes and exit $SCRIPT_NAME."
echo ""
user_selection2=""
while [ "$user_selection2" != "y" ] &&
[ "$user_selection2" != "n" ]
do
echo "Do you wish to cancel? (y/n) :\c"
read user_selection2
case $user_selection2 in
[yY]|[yY][eE][sS]) user_selection2=y;;
[nN]|[nN][oO]) user_selection2=n;;
*) ;;
esac
done
if [ "$user_selection2" = "y" ]
then
exit 0
else
echo ""
continue
fi
else
#// not allowed
continue
fi
fi
if [ $resp_type = "R" ]
then # range
num=`echo $user_selection | grep "^[0-9]*$" | \
awk '{if (($1 >= lower) && ($1 <= upper)) {print $1}}' \
lower=$resp1 upper=$resp2`
if [ "$num" = "$user_selection" ]
then
return
fi
elif [ $resp_type = "Y" ]
then # y/n/yes/no upper or lower
case "$user_selection" in
[yY]|[yY][eE][sS]) user_selection=y
return;;
[nN]|[nN][oO]) user_selection=n
return;;
*) ;;
esac
else # enumeration
if [ "$user_selection" = $resp1 ] || [ "$user_selection" = $resp2 ]
then
return
fi
if [ $resp3 ] && [ "$user_selection" = "$resp3" ]
then
return
fi
fi
done;
}
#================================================================
# Function to get user info.
# Input : $1 - prompt
# $2 - default value (used when // is entered)
# $3 - help function (help functions follow this function)
# $4 - allow blanks (set to "no_blanks" or "blanks_ok")
# $5 - maximum bytes
# Output : user_info
#================================================================
get_info () {
get_info_prompt=$1
default_resp=$2
help_func=$3
blanks=$4
max_bytes=$5
needinfo=$6
while [ 1 = 1 ]
do
user_info=""
# prompt user
echo ""
echo "$get_info_prompt, ? for help or // to cancel."
read user_info
# check for help
if [ "$user_info" = "?" ]
then
if [ "$help_func" != "" ]
then
$help_func
echo ""
fi
continue
fi
# check for blank
if [ "$user_info" = "" ]
then
if [ "$blanks" = "blanks_ok" ]
then
user_info=""
else
echo ""
echo "Information is required."
continue
fi
fi
# check for cancel
if [ "$user_info" = "//" ]
then
# set user response to default ($2) and return
user_info=$default_resp
# check for blank field
if [ "$user_info" = "" ] &&
[ "$blanks" = "no_blanks" -o "$needinfo" = "1" ]
then
#user can exit, or retry the prompt
echo ""
echo "Cancelling now will discard any changes and exit $SCRIPT_NAME."
echo ""
user_info2=""
while [ "$user_info2" != "y" ] &&
[ "$user_info2" != "n" ]
do
echo "Do you wish to cancel? (y/n) :\c"
read user_info2
case $user_info2 in
[yY]|[yY][eE][sS]) user_info2=y;;
[nN]|[nN][oO]) user_info2=n;;
*) ;;
esac
done
if [ "$user_info2" = "y" ]
then
# exit as requested by the user
exit 0
else
# reissue prompt
continue
fi
else
# not cancelling a missing required field, stop prompting
return
fi
fi
# check length
info_len=`echo $user_info | awk '{print length}'`
if [ $info_len -gt $max_bytes ]
then
echo ""
echo "The maximum number of bytes allowed for this field is $max_bytes."
continue
fi
# check for unprintable characters unless user info is null
if [ "$user_info" ]
then
if [ "`echo $user_info | grep '^[ !-~]*$'`" = "" ]
then
echo ""
echo "Unprintable character in '$user_info'."
continue
fi
fi
# upshift response and return
user_info=`echo $user_info | tr "[a-z]" "[A-Z]"`
break
done;
}
# create list of 10.0 patches
ptrack10() {
#added architecture and patch_state for 11.X patches - kc
swlist -v -l fileset -a date -a state -a architecture -a patch_state -a superseded_by 2>/dev/null | \
awk 'BEGIN {start="";lastline=""; fileset=""; yymmdd=""; state=""; arch="";
patch_state=""; superseded_by=""}
{if ($1)
{if ($1 == "fileset")
{start="start"
patch_product=substr(lastline,1,(index(lastline, ".") - 1))
fileset=substr(lastline, (index(lastline, ".") + 1))
}
#need check for date field that is displayed differently using
#11.X SD
else if ($1 == "date")
{if ($2 ~ /[0-9]+/)
{yymmdd = substr($2,7,2)
yymmdd = yymmdd substr($2,1,2)
yymmdd = yymmdd substr($2,4,2)
}
else
{mon=$3
monthno["Jan"] = "01"
monthno["Feb"] = "02"
monthno["Mar"] = "03"
monthno["Apr"] = "04"
monthno["May"] = "05"
monthno["Jun"] = "06"
monthno["Jul"] = "07"
monthno["Aug"] = "08"
monthno["Sep"] = "09"
monthno["Oct"] = "10"
monthno["Nov"] = "11"
monthno["Dec"] = "12"
yymmdd = substr($7,3,2)
yymmdd = yymmdd monthno[mon]
if (length ($4) == 1)
yymmdd = yymmdd "0" $4
else
yymmdd = yymmdd $4
}
}
else if ($1 == "state") {state=$2}
else if ($1 == "architecture") {arch=$2}
else if ($1 == "patch_state") {patch_state=$2}
else if ($1 == "superseded_by") {superseded_by=$2}
else lastline=$1
}
else
{if ((start) && (fileset))
{ if (fileset ~ /PH.._[0-9]*/)
{ if ( ! (patch_state ~ /superseded/) && ! (superseded_by))
{ fileset = substr(fileset,1,10);
state = substr(state, 1,16);
#arch = substr(arch, 1,20);
printf ("PUAD%-10s%s%-16s%-20s\n",
fileset, yymmdd, state, arch)
lastline=""; fileset=""; yymmdd=""; mon=""; month=""
state="";patch_product=""; arch=""
}
}
else if (patch_product ~ /PH.._[0-9]*/)
{ if ( ! (patch_state ~ /superseded/) && ! (superseded_by))
{ patch_product = substr(patch_product,1,10);
state = substr(state, 1,16);
#arch = substr(arch, 1,20);
printf ("PUAD%-10s%s%-16s%-20s\n",
patch_product, yymmdd, state, arch)
lastline=""; fileset=""; yymmdd=""; mon=""; month=""
state="";patch_product=""; arch=""
}
superseded_by=""
fileset=""
}
}
}
}' >> $PSIDIR/$PSIFILE
}
# create list of 10.0 products & filesets
swinv10() {
#added architecture for 11.X patches - kc
swlist -v -l product -a number -a revision -a vendor.tag -a architecture -a patch_state -a superseded_by 2>/dev/null | \
awk 'BEGIN {start="";lastline="";product="";number="";
revision="";vendor="";arch="";patch_state="";superseded_by=""}
{if ($1)
{if ($1 == "product")
{start="start"
product=lastline
}
else if ($1 == "number") {number=$2}
else if ($1 == "revision") {revision=$2}
else if ($1 == "vendor.tag") {vendor=$2}
else if ($1 == "architecture") {arch=$2}
else if ($1 == "patch_state") {patch_state=$2}
else if ($1 == "superseded_by") {superseded_by=$2}
else if ($1 == "vendor") {}
else lastline=$1
}
else
{if ((start) && (product) && (product !~ /PH.._[0-9]*/))
{ if ( ! (patch_state ~ /superseded/) && ! (superseded_by) )
{
product = substr(product, 1,16);
number = substr(number, 1,32);
sub(/[^A-Za-z0-9._].*/, "", revision);
revision = substr(revision,1,32);
vendor = substr(vendor, 1,16);
#arch = substr(arch, 1,20);
printf ("SUADPR%-16s%-32s%-32s%-16s%-20s\n",
product, number, revision, vendor, arch)
lastline=""; product=""; number=""; revision=""; vendor="";
arch="";
}
superseded_by=""
}
}
}' >> $PSIDIR/$PSIFILE
#added architecture for 11.X patches - kc
swlist -v -l subproduct -l fileset -a revision -a date -a architecture -a patch_state -a superseded_by 2>/dev/null | \
awk 'BEGIN {start="";savename=""; product=""; subproduct="";
fileset=""; revision=""; yymmdd=""; arch=""; patch_state="";
productstart=""; savearch=""; superseded_by=""}
{if ($1)
{if ($1 ~ /\./) savename=$1
else if ($1 == "fileset")
{start="start"
nofields=split(savename,fields,".");
product=fields[1];
fileset=fields[nofields];
if (nofields < 3) subproduct="";
else subproduct=fields[2];
}
else if ($1 == "product") # tell arch line to save arch
{productstart="start" # for if no arch on fileset
}
else if ($1 == "revision") revision=$2
else if ($1 == "architecture") {
arch=$2
if (productstart) savearch=$2;
}
else if ($1 == "patch_state") {patch_state=$2}
else if ($1 == "superseded_by") {superseded_by=$2}
#need check for date field that is displayed differently using
#11.X SD
else if ($1 == "date")
{if ($2 ~ /[0-9]+/)
{yymmdd = substr($2,7,2)
yymmdd = yymmdd substr($2,1,2)
yymmdd = yymmdd substr($2,4,2)
}
else
{mon=$3
monthno["Jan"] = "01"
monthno["Feb"] = "02"
monthno["Mar"] = "03"
monthno["Apr"] = "04"
monthno["May"] = "05"
monthno["Jun"] = "06"
monthno["Jul"] = "07"
monthno["Aug"] = "08"
monthno["Sep"] = "09"
monthno["Oct"] = "10"
monthno["Nov"] = "11"
monthno["Dec"] = "12"
yymmdd = substr($7,3,2)
yymmdd = yymmdd monthno[mon]
if (length ($4) == 1)
yymmdd = yymmdd "0" $4
else
yymmdd = yymmdd $4
}
}
}
else
{if ((start) && (fileset) &&
(fileset !~ /PH.._[0-9]*/) && (product !~ /PH.._[0-9]*/))
{ if ( ! (patch_state ~ /superseded/) && ! (superseded_by))
{if ( ! (arch)) arch=savearch
product = substr(product, 1,16);
subproduct = substr(subproduct,1,16);
fileset = substr(fileset, 1,16);
sub(/[^A-Za-z0-9._].*/, "", revision);
revision = substr(revision, 1,32);
#arch = substr(arch, 1,20);
printf ("SUADF2%-16s%-16s%-16s%-32s%s%-20s\n",
product, subproduct, fileset, revision, yymmdd, arch)
savename=""; product=""; subproduct=""; fileset=""
revision=""; yymmdd=""; arch=""
productstart=""
}
}
}
patch_state=""
superseded_by=""
}' >> $PSIDIR/$PSIFILE
}
extract_user_fields() {
systemhandle=`awk '/^HANDLE / {print substr($0, 8)}' $INFOFILE`
}
record_user_fields() {
rm -f $INFOFILE
echo "HANDLE $systemhandle" >> $INFOFILE
}
list_user_fields() {
echo ""
echo "Current contents of $INFOFILE:"
echo ""
echo "System Handle: $systemhandle"
echo ""
}
#--------------------------------------------------------
# user field prompt procedures, so text is not duplicated
#--------------------------------------------------------
# prevent the entry of "0" as this causes COP to crash.
get_handle() {
systemhandle=$1
needinfo=$2
user_info="0"
while [ "$user_info" = "0" ]
do
get_info "Enter the System Handle" \
"$systemhandle" "handle_help" "no_blanks" "20" "$needinfo"
if [ "$user_info" = "0" ]
then
echo '"0" is an invalid value here, perhaps something like "unknown"?'
fi
done;
}
#---------------------------------------
# help display procedures for user field
#---------------------------------------
handle_help() {
echo "The System Handle is the software support contract system identifier."
echo "It can be found on the support contract."
}
prompt_for_psipath() {
echo ""
echo "The default path of the PSIFILE is $PSIDIR. Alternate paths are:"
echo ""
echo " 1 - cwd: $CWD"
echo " 2 - home: $HOMEDIR"
echo " 3 - other"
echo ""
echo "Type RETURN to retain the default path or type the "
echo "corresponding item number to select an alternate path: \c"
#process user input
read user_selection
case $user_selection in
"") ;;
"1") PSIDIR=$CWD;;
"2") PSIDIR=$HOMEDIR;;
"3") while [ -n "$user_selection" ]
do
echo "Enter path name (RETURN for default): \c"
read user_selection
if [ -n "$user_selection" ]
then
if [ -d $user_selection ]
then
if [ -w $user_selection ]
then
PSIDIR=$user_selection
user_selection=
else
echo "No write permission."
fi
else
echo "Not a directory."
fi
fi
done;;
esac
}
write_header() {
typeset -L10 _serial=$systemserial
typeset -L8 _model=$systemmodel
typeset -L20 _handle=$systemhandle
typeset -L24 _group=$groupid
typeset -L4 _office=$systemoffice
typeset -L8 _sh_version=$scriptversion
typeset -L8 _os_version=`uname -r`
typeset -L8 _hw_model=`uname -m`
typeset -L20 _sys_name=`uname -n`
typeset -L20 _model_procs="$new_model/$myprocs"
print -n - "$1" >> $PSIDIR/$PSIFILE ;
print -n - "$_serial" >> $PSIDIR/$PSIFILE ;
print -n - "$_model" >> $PSIDIR/$PSIFILE ;
print -n - "$_handle" >> $PSIDIR/$PSIFILE ;
print -n - "$_group" >> $PSIDIR/$PSIFILE ;
print -n - "$_office" >> $PSIDIR/$PSIFILE ;
print -n - "$_sh_version" >> $PSIDIR/$PSIFILE ;
print -n - "UX" >> $PSIDIR/$PSIFILE ;
print -n - `date +%y%m%d` >> $PSIDIR/$PSIFILE ;
print -n - "$_os_version" >> $PSIDIR/$PSIFILE ;
print -n - "$_hw_model" >> $PSIDIR/$PSIFILE ;
print -n - "$_sys_name" >> $PSIDIR/$PSIFILE ;
print - "$_model_procs" >> $PSIDIR/$PSIFILE ;
}
print_usage() {
echo 'usage: $SCRIPT_NAME [-i -c -b -h -l -p ]';
echo ' i: interactive (cop) mode';
echo ' c: cpm mode';
echo ' b: batch mode, do not prompt, issue error if no info file';
echo ' h: help, print usage info (this text)';
echo ' l: local, create PSIFILE in CWD instead of /tmp';
echo ' p: path, create PSIFILE in specified path';
echo ' ';
echo ' Only one mode (cpm, cop, batch) may be select at a time.';
echo ' The flags -l and -p are used with -c and -b modes';
}
get_num_processors() {
myprocs=
parse_top=`TERM=adm3a top -d1 -n1 | awk '/^Cpu /,/^$/ {print;}' | wc -l`
if (( $parse_top <= 4 ))
then
myprocs=1
else
(( myprocs = parse_top - 5 ))
fi
}
get_new_model()
{
if [ `model` ]
then
new_model=`model | cut -d \/ -f3`
else
new_model=UNKNOWN
fi
}
patches_gt_10()
{
PSIDIR=$1
PSIFILE=$2
header_tag=$3
trailer_tag=$4
# create list of patches
echo ""
echo "Creating list of patches in $PSIDIR/$PSIFILE..."
write_header "$header_tag"
echo "PURE " >> $PSIDIR/$PSIFILE
echo "PUNF " >> $PSIDIR/$PSIFILE
ptrack10
write_header "$trailer_tag"
# create list of products and filesets
echo ""
echo "Creating list of products and filesets in $PSIDIR/$PSIFILE..."
write_header "$header_tag"
echo "SURE " >> $PSIDIR/$PSIFILE
echo "SUNF " >> $PSIDIR/$PSIFILE
swinv10
write_header "$trailer_tag"
}
update_info()
{
needinfo=$1
systemhandle=$2
while [ "$needinfo" = "1" ]
do
echo ""
extract_user_fields
list_user_fields
needinfo=0
get_selection "Any changes (y or n) ?" "Y" "X" "y" "n"
if [ "$user_selection" = "y" ]
then
get_handle "$systemhandle" "$needinfo"
systemhandle="$user_info"
if [ "$user_info" != "//" ]
then
# rewrite file if get_ procedure was called
record_user_fields
fi
# redisplay fields and prompt for more changes
needinfo=1
fi
done
}
confirm()
{
scriptversion=$1
outputtype=$2
echo ""
echo "Copyright (c) Hewlett-Packard 1994-2000. All Rights Reserved."
echo ""
echo " collect.sh version: $scriptversion"
echo ""
echo "This script collects installed patches and filesets from your system"
echo "and packages them in a file for transfer to the Response Center. The"
echo "output of this script, known as a PSIFILE, will be in the format"
echo "$outputtype."
echo
}
check_missing_info()
{
INFOFILE=$1
if [ -f $INFOFILE ]
then
extract_user_fields
else
echo "$INFOFILE file not found, batch mode not complete" 1>&2
exit 1
fi
if [ "$systemhandle" = "" ]
then
exit 1
fi
}
prompt_user_info()
{
INFOFILE=$1
systemhandle=$2
needinfo=$3
# check infofile for user values
if [ -f $INFOFILE ]
then
extract_user_fields
fi
# check for missing field handle then prompt for it.
if [ "$systemhandle" = "" ]
then
get_handle "$systemhandle" "$needinfo"
systemhandle="$user_info"
fi
}
check_spec_path()
{
NUMPARAM=$1
GIVENPATH=$2
if [ $NUMPARAM -eq 0 ]
then
echo "Missing path name."
print_usage
exit 1
fi
if [ $GIVENPATH = "^-.*" ]
then
echo "Missing path name."
print_usage
exit 1
fi
if [ -d $GIVENPATH ]
then
if [ -w $GIVENPATH ]
then
PSIDIR=$GIVENPATH
shift
else
echo "No write permission on specified path."
exit 1
fi
else
echo "Specified path not a directory."
exit 1
fi
}
create_patches()
{
# remove the current file
rm -f $PSIDIR/$PSIFILE
patches_gt_10 "$PSIDIR" "$PSIFILE" "$header_tag" "$trailer_tag"
# inform of results
echo "The file $PSIDIR/$PSIFILE has been created."
}
batch_mode()
{
INFOFILE=$1
systemserial=
systemmodel=
systemhandle=
groupid=
systemoffice=
PSIFILE=PSIFILE
# check infofile for user values
if [ -f $INFOFILE ]
then
extract_user_fields
fi
check_missing_info "$INFOFILE"
create_patches
}
cop_mode()
{
INFOFILE=$1
systemserial=
systemmodel=
systemhandle=""
groupid=
systemoffice=
# outputtype=".txt"
# PSIFILE=`uname -n`.txt
outputtype="PSIFILE-yymmdd-.txt"
PSIFILE=PSIFILE-`date '+%y%m%d'`-`hostname`.txt
needinfo=1
# PSIFILE=PSIFILE
confirm "$scriptversion" "$outputtype"
prompt_user_info "$INFOFILE" "$systemhandle" "$needinfo"
record_user_fields
needinfo=1
update_info "$needinfo" "$systemhandle"
prompt_for_psipath
create_patches
}
cpm_mode()
{
systemserial='NO-SERIAL-'
systemmodel='no-model'
systemhandle='-----NO--HANDLE-----'
groupid='------NO--GROUP-ID------'
systemoffice='-no-'
outputtype=".fs"
PSIFILE=`uname -n`.fs
confirm "$scriptversion" "$outputtype"
create_patches
}
#################################################################
# main() #
#################################################################
get_num_processors
get_new_model
while [ $# -gt 0 ]
do
case $1 in
-c) CPM=true ; shift;;
-i) COP=true ; shift;;
-b) BATCH=true ; shift;;
-l) DIR=$CWD ; shift;;
-p) shift; check_spec_path "$#" "$1"; shift;;
-h) print_usage; exit 1;;
*) print_usage; exit 1;;
esac
done
if [ "$COP" = "true" ]
then
if "$BATCH" = "true" || "$CPM" = "true"
then
echo "incompatible flags used"
exit 1
else
cop_mode "$INFOFILE"
fi
elif [ "$CPM" = "true" ]
then
if "$BATCH" = "true" || "$COP" = "true"
then
echo "incompatible flags used"
exit 1
else
cpm_mode
fi
elif [ "$BATCH" = "true" ]
then
if "$CPM" = "true" || "$COP" = "true"
then
echo "incompatible flags used"
exit 1
else
batch_mode "$INFOFILE"
fi
else
# If no flags used on command line default here
# Two default modes. CPM no prompts. COP prompt for handle.
# CPM creates output to hostname.fs. COP sends output to PSIFILE
cpm_mode
#cop_mode "$INFOFILE"
fi
###############################################################################