return to PRS Technologies website


cpm_collect.sh
############################################################################### #!/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 <path>]'; 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="<hostname>.txt" # PSIFILE=`uname -n`.txt outputtype="PSIFILE-yymmdd-<hostname>.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="<hostname>.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 ###############################################################################