#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos72X src/bos/usr/bin/oslevel/oslevel.sh 1.5.5.5 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1993,2021 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)40        1.5.5.5  src/bos/usr/bin/oslevel/oslevel.sh, cmdswvpd, bos72X, x2021_25A4 6/17/21 13:42:56
#
#   COMPONENT_NAME: CMDSWVPD
#
#   FUNCTIONS:  usage
#               toomanylevels
#               interrupted
#
#   ORIGINS: 27
#
#
#   (C) COPYRIGHT International Business Machines Corp. 1993
#   All Rights Reserved
#   Licensed Materials - Property of IBM
#   US Government Users Restricted Rights - Use, duplication or
#   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
#
# Print usage message if invalid arguments specified
#

export PATH=/usr/bin:/usr/sbin
unalias -a
umask 133

trap interrupted INT QUIT TERM EXIT

########################################################################
# Function: getfsfree()  (Get filesystem free space)
########################################################################

getfsfree()
{
   typeset FS="$1"  # File system
   typeset DF="/usr/bin/df -P"
   typeset AWK=/usr/bin/awk
   typeset ERROR='eval /usr/sbin/inuumsg 331 "oslevel:" "getfsfree()"; return 1'
   [[ -z $FS ]] && $ERROR

   ERROR='eval /usr/sbin/inuumsg 353 "oslevel:" "$FS"; return 1'
   BUF=$(LC_ALL=C LANG=C $DF $FS/)
   [[ $? -ne 0 || -z $BUF ]] && $ERROR

   BUF=$(echo "$BUF" | $AWK '{getline; print $4}')
   RC=$?
   isnum "$BUF" || $ERROR 

   echo "$BUF"
   return 0

}  # end of getfsfree()

########################################################################
## Function: isnum
## Returns: 0 = STR is all digits 0-9, 1 = STR is not all digits
########################################################################

isnum()
{
   typeset STR="$1"
   typeset ERROR='eval /usr/sbin/inuumsg 331 "oslevel:" "isnum()"; return 1'
   typeset COUNT=0

   STR=${STR#-} # remove negative
   [[ -z "$STR" ]] && return 1

   while [[ -n "$STR" ]]; do
     [[ "$STR" = "${STR%[0-9]}" ]] && return 1
     STR=${STR%[0-9]}

     # loop safety
     (( COUNT = $COUNT + 1 ))
     [[ $COUNT -gt 40000 ]] && $ERROR

   done

   return 0

}  # end of isnum()

########################################################################
## Function: check_work_space
## Returns: 0 / 1
########################################################################

check_work_space()
{
   typeset TARGET="$1"
   typeset NEED_SPACE="$2"
   typeset ERROR='eval return 1'
   typeset BUF
   typeset DEFICIT
   typeset RC=0 

   [[ -n $INUBOSTYPE || -n $INUCLIENTS || $NEED_SPACE_MSG -eq 1 ]] && return 0

   [[ -z $TARGET ]] && RC=1
   isnum $NEED_SPACE || RC=1

   if [[ $RC -ne 0 ]]; then
      /usr/sbin/inuumsg 331 "oslevel:" "check_work_space()"
      $ERROR
   fi

   # Get TARGET's free size
   BUF=$(getfsfree $TARGET) || $ERROR

   if [[ $NEED_SPACE -gt $BUF ]]; then
      (( DEFICIT = $NEED_SPACE - $BUF ))
      /usr/sbin/inuumsg 355 "oslevel:" "/tmp" "$DEFICIT"
      NEED_SPACE_MSG=1 
      $ERROR
   fi

   return 0

}  # check_work_space()

print_min_spack()
{
   typeset ERROR='eval /usr/sbin/inuumsg 216 110 >&2; exit 1'
   typeset BUF
   typeset lev

   # print out vrm0-00-00 using bos.rte vrmf
   BUF=$(LC_ALL=C /usr/bin/lslpp -qlc bos.rte | /usr/bin/awk 'FNR <= 1') || $ERROR
   BUF=$(echo "$BUF" | LC_ALL=C /usr/bin/awk -F: '{split($3,lev,"."); 
				print lev[1]lev[2]lev[3]"0"; exit(0)}')
   [[ $? -ne 0 || -z $BUF ]] && $ERROR
   echo "${BUF}-00-00"
   return 0

}  # end of print_min_spack()

print_min_rml()
{
   typeset ERROR='eval /usr/sbin/inuumsg 216 110 >&2; exit 1'
   typeset BUF
   typeset lev

   [[ $recml -ne 1 ]] && return 0

   # There is no RML information, lets print out
   # VRMF-00.
   BUF=$(LC_ALL=C /usr/bin/lslpp -qlc bos.rte | /usr/bin/awk 'FNR <= 1') || $ERROR
   BUF=$(echo "$BUF" | LC_ALL=C awk -F: '{split($3,lev,"."); 
         print lev[1]lev[2]"00"; exit(0)}')
   [[ $? -ne 0 || -z $BUF ]] && $ERROR
   echo "${BUF}-00"
   return 0

}  # end of print_min_rml()

print_current_ml()
{
   typeset lev
   typeset ERROR='eval /usr/sbin/inuumsg 216 111 >&2; exit 1'
   BUF=$(LC_ALL=C /usr/bin/lslpp -qlc bos.rte | /usr/bin/awk 'FNR <= 1') || $ERROR
   BUF=$(echo "$BUF" | LC_ALL=C awk -F: '{split($3,lev,".");
         print lev[1]"."lev[2]"."lev[3]".0"; exit(0)}')
   [[ $? -ne 0 || -z $BUF ]] && $ERROR
   echo "$BUF"
   return 0
    
}  # end of print_current_ml()

loop_create_mlinfo()
{
   typeset MAXLOOP=120    # max number we will wait/loop
   typeset LOCKED=1       # someone else has the lock or not
   typeset LOOPC          # loop counter
   typeset RC=0           # return code
   typeset LOOP=1         # loop conditional variable

   # record original OS_ACT
   typeset ORIG_OS_ACT=$OS_ACT

   while [[ $LOOP = 1 ]]; do

      (( LOOPC = $LOOPC + 1 ))
      if [[ $LOOPC -gt $MAXLOOP ]]; then
         /usr/sbin/inuumsg 212
         return 1
      fi

      # reset OS_ACT to original
      OS_ACT=$ORIG_OS_ACT

#############################################################
# Check if the -f flag was give. If it was not, go through
# standard cache checks. If it was we know we will have
# to rebuild the given cache and invalidate both.
#############################################################

      if [[ $force_cache_build -ne 1 ]]; then

         # Check if the cache in questions is still good.
         check_cache $usecache
         RC=$?

         if [[ $RC -lt 99 ]]; then
            (( OS_ACT = $OS_ACT + $RC ))
         else
            /usr/sbin/inuumsg 215 >&2
            /usr/sbin/inuumsg 214 >&2
            return 1
         fi

      else

         # If force flag used, make sure we invalidate both caches.
         (( OS_ACT = $OS_ACT + 4 ))

      fi

      # Check that we have enough space in /tmp for work and tmp files.
      # If we do not, we issue a warning and keep going. The current
      # default space requirement is 10496 512bb (5.1 megs). The user 
      # can overwrite the default by setting the OSLEVEL_WORK_SPACE_REQ 
      # variable.
      
      [[ -z $OSLEVEL_WORK_SPACE_REQ ]] && OSLEVEL_WORK_SPACE_REQ=10496   
      check_work_space /tmp $OSLEVEL_WORK_SPACE_REQ
      
      # Run the cache/mlinfo builder. If it fails, we have to quit.
      # If someone else has the lock, we go to the top of the loop.

      rebuild_cache ; RC=$?

      if [[ $RC -eq $NOLOCK ]]; then
         /usr/bin/sleep 1
         continue
      fi
        
      [[ $RC -ne 0 ]] && return 1

      if [[ ! -r $mlinfo && $recml = 1 ]]; then
         /usr/sbin/inuumsg 216 109 >&2
         /usr/sbin/inuumsg 214 >&2
         return 1
      fi

      # if we got here, then we build mlinfo successfully
      LOOP=0
      break

   done

}  # end of loop_create_mlinfo()

rebuild_cache()
{

   trap '' 1 2 3 
   typeset rc 
  
   # Execute "re-make maint level cache file" 
   /usr/bin/rm_mlcache_file $UID $GID
   rc=$?

   [[ $rc -eq $NOLOCK ]] && return $rc

   if [[ $rc -gt 203 && $rc -lt 211 ]]; then
      /usr/sbin/inuumsg 213 2>&1
   elif [[ $rc -ne 0 ]]; then
      /usr/sbin/inuumsg 216 $rc 2>&1 
      /usr/sbin/inuumsg 214 2>&1
   fi

   return $rc
}

check_cache()
{

   trap interrupted INT QUIT TERM

   # Get the maintenance level information from the fix database
   # This information is cumulatively refreshed with each maintenance level,
   # but first check to see if we can reuse old instfix output.  We do this
   # by making sure the mlcache file exists and has a size greater than 0.
   # We also do checksum comparisons to see if there have been any
   # changes since the cache was taken.  The previous sum on USR
   # part history is kept in MLCACHE_SUM_FILE. 
   #      
   # RETURN CODES:
   #  0 = Rebuild Cache for the given info type (ml or rml)
   #  2 = No need to rebuild cache 
   #  4 = Cache sum is not current (remove both), rebuild info type
   # 99 = A severe error has occurred


   # If this force flag is used, then there is no point in
   # doing the rest. We should not really ever get here
   # if it is set.. so just in case.               
 
   [ $force_cache_build -gt 0 ] && return 4

   # Init local vars.
   typeset MLCACHE="$1"
   typeset MLCACHE_SUM_FILE="$instlib/.oslevel.cache.sum"
   typeset HISTFILE=/usr/lib/objrepos/history
   typeset MLCACHE_SUM_OLD=0 
   typeset MLCACHE_SUM_NEW=0 

   if [ -s "$MLCACHE_SUM_FILE" -a -r "$MLCACHE_SUM_FILE" ]; then
   
      # Get the old sum
      MLCACHE_SUM_OLD=$(cat $MLCACHE_SUM_FILE 2>/dev/null) || return 0

      # Get the new sum
      MLCACHE_SUM_NEW=$(/usr/bin/sum "$HISTFILE"  2>/dev/null) || return 99
      MLCACHE_SUM_NEW=${MLCACHE_SUM_NEW%%" "*} || return 99

      # Compare new and old, if they are the same then we do not need
      # to rebuild cache

      [ "$MLCACHE_SUM_NEW" != "$MLCACHE_SUM_OLD" ] && return 4

   else
     
      # The cache sum file is not valid or not there, that means we 
      # need to create it and invalidate all current caches 

      return 4

   fi

   # If $MLCACHE does not exist or 0 size or not readable, then 
   # we need to build

   [ -z "$MLCACHE" -o ! -r "$MLCACHE" -o ! -s "$MLCACHE" ] && return 0

   # If we get here, then the current cache is OK to use
   
   return 2 

}

get_known_rmls()
{
   trap interrupted INT QUIT TERM
   typeset BUF
       
   BUF=$(print_min_rml)

   if [[ ! -s $mlinfo ]]; then
      KWN_RML_LEVS=$BUF
      return 0
   fi

   KWN_RML_LEVS=$( /usr/bin/awk -F: '$1 ~ /_AIX_ML$/ { print $1 }' $mlinfo | \
                   /usr/bin/sort -r | /usr/bin/uniq)
 		
   if [ $? -ne 0 -o -z "$KWN_RML_LEVS" ]; then
      /usr/sbin/inuumsg 211 2>&1
      exit 1
   fi

   KWN_RML_LEVS="${KWN_RML_LEVS}"
   return 0
}

# This function get_known_spacks() gets all service pack related info into
# KWN_SP_LEVS. Sorting will be done on KWN_SP_LEVS in reverse order so
# the first SP in the list will be the highest SP available on the machine.
get_known_spacks()
{
   trap interrupted INT QUIT TERM
   typeset BUF
   typeset MVRMF
   typeset SPNO
   typeset TLNO
       
   #MVRMF is used to store the VRMF of the service pack
   #For new format SP's (ex: 53-07-012312_SP) this will be used to make
   #53 as 5300 for display purpose.
   #TLNO will be used to store TL number of a SP
   #SPNO will be used to distinguish old format SP numbers and new format
   #SP numbers and this will be used to separate date field from SP number
   
   # always report at least the current RML "-00"
   BUF="$(print_current_rml)-00_SP"

   if [[ ! -s $mlinfo ]]; then
      KWN_SP_LEVS=$BUF
      return 0
   fi

   KWN_SP_LEVS=$( /usr/bin/awk -F: '$1 ~ /_SP$/ { print $1 }' $mlinfo | \
                   /usr/bin/sort -t- -r | /usr/bin/uniq)
 		
   # Sort current RML into known SP levels
   KWN_SP_LEVS="$(for i in ${KWN_SP_LEVS} ${BUF}; do echo $i; done | \
				/usr/bin/sort -t- -r)"
   
   #prepare SP's for display  in new SP format
   KWN_SP_LEVS="$(for i in ${KWN_SP_LEVS} ; do
	   MVRMF=`echo $i | cut -f 1 -d -`
	   if [ $MVRMF -lt 100 ]
	   then
		  MVRMF=$MVRMF\00
	   fi
	   SPNO=`echo $i | cut -f 3 -d -`
	   SPNO=`echo $SPNO  | cut -f 1 -d _`
	   if [ $(echo $SPNO | awk '{len=length($1); print len;}') -lt 6 ]
	   then
	      SPNO=$SPNO\-0000
       else
		  SPNO=$(echo $SPNO | awk '{a=substr($1,0,2); print a;}')\-"$(echo $SPNO |awk '{a=substr($1,3); print a;}')"
	   fi
	   TLNO=`echo $i | cut -f 2  -d -`
	   MVRMF=$MVRMF\-"$TLNO"\-"$SPNO"\_SP
	   echo $MVRMF
	   done
	   )"
    # sort the SP's in reverse order, highest level SP should be the first SP in the list
	KWN_SP_LEVS="$(for i in ${KWN_SP_LEVS}; do echo $i; done | \
			 /usr/bin/sort -t- -r)"

   return 0

} # end of get_known_spacks()

print_current_rml()
{
	typeset lev
	trap interrupted INT QUIT TERM

	get_known_rmls
	missing_list=$(/bin/grep _AIX_ML $mlinfo | \
	  grep ":-:" | /usr/bin/awk -F: '{ print $1 }' | /usr/bin/sort -r | \
	  /usr/bin/uniq )
        
	for lev in $(echo "$KWN_RML_LEVS"); do
		echo "$missing_list" | grep "$lev" > /dev/null 2>&1
		if [[ $? -ne 0 ]]; then
	 		echo "${lev%_AIX_ML}"
			break
		fi	
	done
	
	return 0
}

print_current_spack()
{
	trap interrupted INT QUIT TERM
	typeset BUF
	typeset DVRMF
	typeset DSPNO
	typeset DTLNO
	typeset lev

	get_known_spacks
	missing_list=$(/bin/grep "_SP:" $mlinfo | /bin/grep ":-:" | \
           /usr/bin/awk -F: '{ print $1 }' | /usr/bin/sort -r | /usr/bin/uniq )
        
	#prepare the missing list to sync with new SP names as did in get_known_spacks
	missing_list="$(for i in ${missing_list}; do
		DVRMF=`echo $i | cut -f 1 -d -`
		if [ $DVRMF -lt 100 ]
		then
			DVRMF=$DVRMF\00
		fi
		DSPNO=`echo $i | cut -f 3 -d -`
		DSPNO=`echo $DSPNO  | cut -f 1 -d _`

		if [ $(echo $DSPNO | awk '{len=length($1); print len;}') -lt 6 ]
		then
			DSPNO=$DSPNO\-0000
		else
			DSPNO=$(echo $DSPNO | awk '{a=substr($1,0,2); print a;}')\-"$(echo $DSPNO |awk '{a=substr($1,3); print a;}')"
		fi

		DTLNO=`echo $i | cut -f 2  -d -`
		DVRMF=$DVRMF\-"$DTLNO"\-"$DSPNO"\_SP
		echo $DVRMF
		done
	)"
	for lev in $(echo "$KWN_SP_LEVS"); do
		echo "$missing_list" | /bin/grep "$lev" > /dev/null 2>&1
		if [[ $? -ne 0 ]]; then
		   # SP level is complete; check if related RML is complete
		   BUF="$(echo $lev | /usr/bin/sed 's:CSP-0000_SP:00-0000_SP:')"
		   BUF="$(echo $BUF | /usr/bin/sed 's:..-...._SP:00:')"
		   echo "$KWN_SP_LEVS" | /usr/bin/grep "$BUF" > /dev/null 2>&1
		   if [[ $? -ne 0 ]]; then
		      # related RML not found (not complete) so keep looking
		      continue
		   fi
	 	   echo "${lev%_SP}"
		   break
		fi	
	done
	
	return 0
} # end of print_current_spack()

print_known_rmls()
{
	typeset lev
	trap interrupted INT QUIT TERM

	get_known_rmls
	/usr/sbin/inuumsg 208

	for lev in $(echo "$KWN_RML_LEVS"); do
		echo ${lev%_AIX_ML}
	done
}

print_known_spacks()
{
	typeset lev
	trap interrupted INT QUIT TERM

	get_known_spacks
	/usr/sbin/inuumsg 726

	for lev in $(echo "$KWN_SP_LEVS"); do
		echo ${lev%_SP}
	done
} # end of print_known_spacks()

get_diff_spacks()
{
	trap interrupted INT QUIT TERM

	# Modify nlevel name format to match with fix db name
	nlevel=`echo $nlevel | awk -F "-" '{ print substr($1,1,2) "-" $2 "-" $3$4}'`

	drmls_list=$(/bin/grep -E "${SPL}_SP:|${nlevel}_SP:" $mlinfo)
 
	if [ -z "$drmls_list" ]; then
		/usr/sbin/inuumsg 727 "$SPL" >&2
		exit 1
	fi
        
        drmls_list=$(echo "$drmls_list" | /bin/grep ":$P_FLAG:" 2> /dev/null)

        # check that there is work to be done
	if [ -z "$drmls_list" ]; then
     		exit 0
 	fi

	/usr/sbin/inuumsg 725

  	echo "$drmls_list" | /usr/bin/awk -F: '{ 
   			printf ("%-39s %-18s %-15s\n", $2, $4, $3)  }'
 
 	if [ $? -ne 0 ]; then
		/usr/sbin/inuumsg 728 >&2
		exit 1
	fi  

	return 0
} # end of get_diff_spacks()

get_diff_rmls()
{
	trap interrupted INT QUIT TERM

	drmls_list=$(/bin/grep "$RML"_AIX_ML $mlinfo)
 
	if [ -z "$drmls_list" ]; then
		/usr/sbin/inuumsg 209 "$RML" >&2
		exit 1
	fi
        
        drmls_list=$(echo "$drmls_list" | /bin/grep ":$P_FLAG:" 2> /dev/null)

        # check that there is work to be done
	if [ -z "$drmls_list" ]; then
     		exit 0
 	fi

	/usr/sbin/inuumsg 207

  	echo "$drmls_list" | awk -F: '{ 
   			printf ("%-39s %-22s %-15s\n", $2, $4, $3)  }'
 
 	if [ $? -ne 0 ]; then
		/usr/sbin/inuumsg 210 >&2
		exit 1
	fi  

	return 0
}

usage () {
# Message 724 with the updated usage is ready for use in 5.4
	/usr/sbin/inuumsg 724 2>&1
	exit 1
}

#
# User specified more than one of -l, -g, -q
#
toomanylevels () {
	/usr/sbin/inuumsg 164 2>&1
	usage
	exit 2
}

#
# User interrupted command
#
interrupted () {
     /usr/bin/rm -f $mlinfo
     /usr/bin/rm -rf $tmpdir
}

#
# Main logic for oslevel
#

# undocumented flag for debugging
for opt in $(echo $@)
do
        if [ "$opt" = "-D" ]; then
                set -x
                for i in $(typeset +f); do typeset -ft $i; done
        fi
done

basic=1		# Basic form of output requested
backward=0	# Backward compatibility for "-g" flag
downlevel=0	# Products below maintenance level requested
postlevel=0	# Products updated since maintenance level requested
recml=0		# Recommended Preventive Maintenace Levels
spack=0		# Service Packs
query=0		# Query of known maintenance levels requested
level=		# Maintenance level specified with -l
export OS_ACT=0 # Oslevel action variable.
export NOLOCK=99 # nolock return from rm_mlcache_file
UID=$(/usr/bin/id -u)
GID=$(/usr/bin/id -g)
export force_cache_build=0
instlib="/tmp/.oslevel.datafiles"
mlcache="$instlib/.oslevel.mlinfo.cache"
rmlcache="$instlib/.oslevel.rml.cache"
tmpdir="/tmp/oslevel.$UID.$$"
mlinfo="$tmpdir/.oslevel.mlinfo"
usecache=""
MLTAG="_AIX_ML"
mlfound=0
export NEED_SPACE_MSG=0
nlevel= 

trap interrupted INT QUIT TERM EXIT

# Test for version 4 or greater
if [ $(uname -v) -lt 4 ]
then
	/usr/sbin/inuumsg 165 2>&1
	exit 6
fi

# process valid options, watching for invalid combinations

while getopts ":l:g:fDqrs" OPTION
do
	case $OPTION in
                 D) set -x
                    for i in $(typeset +f); do typeset -ft $i; done
                    ;;
	 	 l) downlevel=1
		    basic=0
	 	    level=$OPTARG
		    P_FLAG="-" 
		    [ -z "$level" ] && usage
		    ;;
		 g) postlevel=1
		    basic=0
		    level="$OPTARG"
		    P_FLAG="+"	
		    ;;
		 r) recml=1
	            ;;		
		 s) spack=1
	            ;;		
	   	 q) query=1
		    basic=0
		    ;;
		 f) force_cache_build=1   
		    ;;
		\?) usage
		    ;;
		 :) if [ "$OPTARG" = "g" ]; then
			# backward compatibility for "-g" flag	
			backward=1	
			postlevel=1
			basic=0
		    else
			usage
		    fi	
		    ;;
	esac
done

if [ $backward -eq 1 -a $recml -eq 1 ]; then
	usage
fi

if [[ "$level" = "-"* ]]; then
	usage
fi

if [ $backward -eq 1 -a $spack -eq 1 ]; then
	usage
fi

if [ $spack -eq 1 -a $recml -eq 1 ]; then
	usage
fi
# This causes us to use the RML cache for Service Pack requests.
# Below we process spack eq 1 before recml eq 1 so that we get the SP logic.
if [ $spack -eq 1 ]; then
	recml=1
fi

[ $(expr $downlevel + $postlevel + $query) -gt 1 ] && toomanylevels

# Here are the variables for OS_ACT
#   1 = Rebuild ml(release cache) if needed
#   2 = Rebuild rml if needed
#   3 = Build mlinfo for ml(release cache) only.
#   4 = Build mlinfo for rml only.
#   5 = Cache expired, rebuild ml, remove both
#   6 = Cache expired, rebuild rml, remove both 
 
# Set the usecashe variable to use the correct cache to check. 
# usecache is for the check_cache() function

if [[ $recml -ne 1 ]]; then
   usecache=$mlcache
   export OS_ACT=1 
else
   usecache=$rmlcache
   export OS_ACT=2  
fi

loop_create_mlinfo || exit 1

# Process service pack operation.
if [[ $spack = 1 ]]; then
	if [[ $downlevel = 1 || $postlevel = 1 ]]; then

	# Save the SP Name to nlevel. level is modified to remove build date
		nlevel=$level
		level=`echo $level | cut -f "1 2 3" -d "-"`

####################################################################
## If this is a diff operation and spack is set, we need to check
## if they specified the minimal level (vrmf-00-00). If they have,
## we look for everything above the current_ml (v.r.m.f).
####################################################################
 
                if [[ "$level" = *"-00-00" ]]; then

                   SPL=$(print_min_spack)

                   if [[ "$SPL" = "$level" ]]; then
                      # Reset the variables, rebuild the cache, then drop thru.
                      recml=0 
                      level=$(print_current_ml)
                      usecache=$mlcache
                      OS_ACT=1
                      loop_create_mlinfo || exit 1
                   else
                      SPL="$level"
                      get_diff_spacks
                      exit 0
                   fi

####################################################################
## If they specified the minimal SP (vrmf-ll-00),
## we look for everything above the current RML (vrmf-00).
####################################################################

                elif [[ "$level" = *"-00" ]]; then

                   SPL="$(print_current_rml)-00"

                   if [[ "$SPL" = "$level" ]]; then
                      # just set level and drop thru. Everything else is OK.
                      level=$(print_current_rml)
                   else
                      /usr/sbin/inuumsg 727 "$level" >&2
                      exit 1
                   fi

                else  # $level is not  *"-00"
 
                     SPL="$level"
                     get_diff_spacks
                     exit 0

                fi   # end of "$level" = *"-00-00"
           
        else
                if [[ $query = 1 ]]; then
                        print_known_spacks
                        exit 0
                else
                        print_current_spack
                        exit 0
                fi
        fi
fi

# Process recommended ml operation.
if [[ $recml = 1 ]]; then
	if [[ $downlevel = 1 || $postlevel = 1 ]]; then

####################################################################
## If this is a diff operation and recml is set, we need to check
## if they specified the minimal level (VRMF-00). If they have,
## we look for everything above the current_ml (V.R.M.F).
####################################################################
 
                RML="$level"

		if [[ "$level" = *"-00" ]]; then
                   /usr/sbin/inuumsg 209 "$RML" >&2
                   exit 1

#		   RML=$(print_min_rml)

#                   if [[ "$RML" = "$level" ]]; then
#                      recml=0 
#		      level=$(print_current_ml)
#                      usecache=$mlcache
#                      OS_ACT=1
#		      loop_create_mlinfo || exit 1
#                   else
#		      RML="$level"
#		      get_diff_rmls
#                      exit 0
#                   fi

                else  # $level is not  *"-00"
 
                     RML="$level"
                     get_diff_rmls
                     exit 0

                fi   # end of "$level" = *"-00"
           
        else
                if [[ $query = 1 ]]; then
                        print_known_rmls
                        exit 0
                else
                        print_current_rml
                        exit 0
                fi
        fi
fi

# Process standard release info

if [[ ! -s $mlinfo ]]
then
	echo `LC_ALL=C /usr/bin/lslpp -qlc bos.rte | /usr/bin/awk 'FNR <= 1' | cut -d':' -f3 | cut -d'.' -f1-2`.0.0
	# /usr/sbin/inuumsg 166
	/usr/bin/rm -f $mlinfo 
        rm -rf $tmpdir
	exit 0
fi

# If level has been specified, make sure it exists
if [ -n "$level" ] && (cut -d: -f1 $mlinfo | /usr/bin/grep -q "$level$MLTAG$")
then
	:
else
   if [ -n "$level" ]
   then
	/usr/sbin/inuumsg 167 $level 2>&1
	#/usr/bin/rm $mlinfo
	exit 1
   fi
fi

# If query mode, list the available levels, most recent first, then end.
if [ $query -eq 1 ]
then
	/usr/sbin/inuumsg 168
	cut -d':' -f1 $mlinfo | sed 's:_AIX_ML::' | sort -n -r -t . | uniq
        #/usr/bin/rm $mlinfo
	exit 0
fi

# Determine most recently complete maintenance level 
if [ -z "$level" ]
then
	# Get list of maintenance levels, most recent first
	cut -d':' -f1 $mlinfo | sort -n -r -t . | uniq |
	# Check instfix output to see if any have no downlevel filesets
	while read ml
	do
	   /bin/grep "^$ml" $mlinfo |\
              /bin/grep -q ":-:"
	   if [ $? -eq 1 ]
	   then
	      level=`echo $ml | sed "s:$MLTAG::"`
	      # If we're just checking for the most recent complete ML
	      if [ $basic -eq 1 ]
	      then
		 echo $level
		 exit 0
	      fi
	      mlfound=1
	      break
	   fi
	done
	# If no maintenance levels exist, then we have to punt....
	if [ $mlfound -eq 0 ]
	then
	   baselevel=`LC_ALL=C lslpp -qLc bos.rte | cut -d':' -f3 | cut -d'.' -f1-2`.0.0
	   if [ $basic -eq 1 ]
	   then
	      echo $baselevel
	      exit 0
	   elif [ $postlevel -eq 1 ]
	   then
	      LC_ALL=C /usr/bin/lslpp -qLc bos.\* printers.\* devices.\* X11.\* 2>/dev/null |
              /usr/bin/awk -F: -v header=0 -v oslevel="$baselevel" \
	          '$3 > oslevel {
           	   if ( header == 0 ) 
           	   { 
	       	       system("/usr/sbin/inuumsg 170"); 
	               header = 1 
                   }
                   printf("%-40s%-20s%s\n",$2,$3,oslevel) 
              }'

	      exit 0
	   fi
	fi
fi

if [[ $postlevel -eq 1 ]]
then
   diffsym="+"
else
   diffsym="-"
fi

/bin/grep "^$level$MLTAG:" $mlinfo |\
   /usr/bin/awk -F: -v header=0 -v diffsymbol="$diffsym" '$5 == diffsymbol {
           if ( header == 0 ) 
           { 
	       system("/usr/sbin/inuumsg 170"); 
	       header = 1 
           }
           printf("%-40s%-20s%s\n",$2,$4,$3) 
       }'

# Goodbye
#/usr/bin/rm $mlinfo 
exit 0