#!/bin/bash

#< Grab specific information from RPM headers, and display in order specified 

# Only caveat here is you can't use this script the way getopts is itended, i.e.
# mycmd -pvPsr

# Reason? Because I wanted to allow ordering of options, thus
# mycmd -p -P -v
# and
# mycmd -P -v -p
# are two different output formats

# Executable paths
BASENAME="/bin/basename"
CUT="/usr/bin/cut"
ECHO="/bin/echo"
EGREP="/bin/egrep"
GREP="/bin/grep"
RM="/bin/rm"
RPM="/bin/rpm"
SED="/bin/sed"
SORT="/bin/sort"
UNAME="/bin/uname"
WC="/usr/bin/wc"

# RPM with options
RPM_ALL="${RPM} -qa"
RPM_DETAIL="${RPM} -qi"

# File paths
REDHAT_RELEASE="/etc/redhat-release"

# Option modes
CSV_MODE=0
FULL_PKG_NAME=0
PKG_NAME=0
REL_NUM=0
SUMMARY=0
VER_NUM=0

# Other vars
DELIM=" "
THIS_PROG=$( ${BASENAME} $0 )
TMPFILE="/tmp/${THIS_PROG}.$$"

# Exit codes
SUCCESS=0
ERROR=1

function cleanup {
   ${RM} -f ${TMPFILE}
}

trap "cleanup; exit ${ERROR}" 1 2 3 15

function print_error {
   ${ECHO} "Error: $@" >&2 
}

function print_usage {
   {
      ${ECHO} "Usage: ${THIS_PROG} [-c] [-p][-P][-r][-s][-v]"
      ${ECHO} "           -c  Print output in csv format"
      ${ECHO} "           -p  Show short package name"
      ${ECHO} "           -P  Show full package/rpm name"
      ${ECHO} "           -r  Show release"
      ${ECHO} "           -s  Show package summary"
      ${ECHO} "           -v  Show version"
   } >&2
}

function check_os {
   OS=$( ${UNAME} )
   case ${OS} in
      "Linux") if [ ! -f "${REDHAT_RELEASE}" ]; then
                  print_error "Only Redhat Linux is supported by this script"
                  exit ${ERROR}
               fi 
               ;;
      *      ) print_error "Only Redhat Linux is supported by this script" 
               exit ${ERROR} 
               ;;
   esac
}

function get_rpm_info {
   if [ "${CSV_MODE}" -eq "1" ]; then
      DELIM=","
   fi
   ${RPM_ALL} | ${SORT} -k 1,1 | while read PACKAGE; do
      if [ "${FULL_PKG_NAME}" -eq "1" ]; then
         ${ECHO} "PACKAGE=${PACKAGE}" >> ${TMPFILE}
      fi
      ${RPM_DETAIL} ${PACKAGE} | while read DETAIL; do
         if [ "${PKG_NAME}" -eq "1" ]; then
            ${ECHO} "${DETAIL}" | ${EGREP} '^Name[[:space:]]+:' >/dev/null 2>&1
            if [ "$?" -eq "0" ]; then
               pNAME=$( ${ECHO} "${DETAIL}" | ${EGREP} '^Name[[:space:]]+:' |\
                        ${SED} 's/^Name[ ][ ]*:[ ]\([^ ]*\)[ ][ ]*.*$/\1/' )
               ${ECHO} "pNAME=${pNAME}" >> ${TMPFILE}
            fi
         fi

         if [ "${VER_NUM}" -eq "1" ]; then
            ${ECHO} "${DETAIL}" | ${EGREP} '^Version[[:space:]]+:' >/dev/null 2>&1
            if [ "$?" -eq "0" ]; then
               pVERSION=$( ${ECHO} "${DETAIL}" | ${EGREP} '^Version[[:space:]]+:' |\
                        ${SED} 's/^Version[ ][ ]*:[ ]\([^ ]*\)[ ][ ]*.*$/\1/' )
               ${ECHO} "pVERSION=${pVERSION}" >> ${TMPFILE}
            fi
         fi

         if [ "${REL_NUM}" -eq "1" ]; then
            ${ECHO} "${DETAIL}" | ${EGREP} '^Release[[:space:]]+:' >/dev/null 2>&1
            if [ "$?" -eq "0" ]; then
               pRELEASE=$( ${ECHO} "${DETAIL}" | ${EGREP} '^Release[[:space:]]+:' |\
                        ${SED} 's/^Release[ ][ ]*:[ ]\([^ ]*\)[ ][ ]*.*$/\1/' )
               ${ECHO} "pRELEASE=${pRELEASE}" >> ${TMPFILE}
            fi
         fi
 
         if [ "${SUMMARY}" -eq "1" ]; then
            ${ECHO} "${DETAIL}" | ${EGREP} '^Summary[[:space:]]+:' >/dev/null 2>&1
            if [ "$?" -eq "0" ]; then
               pSUMMARY=$( ${ECHO} "${DETAIL}" | ${EGREP} '^Summary[[:space:]]+:' |\
                        ${SED} -e 's/^Summary[ ][ ]*:[ ]\(.*\)/\1/' -e 's/,//g' )
               ${ECHO} "pSUMMARY=${pSUMMARY}" >> ${TMPFILE}
            fi
         fi
      done
      # The reason we do this is so that ordering of output fields is honoured
      OPT_LIST=$( ${ECHO} "${FULL_CMD_LIST}" |\
                  ${SED} -e 's/-c//g' -e 's/-p/pNAME/g' -e 's/-P/PACKAGE/g' \
                  -e 's/-r/pRELEASE/g' -e 's/-s/pSUMMARY/g' -e 's/-v/pVERSION/g' )
      NUM_PARAMS=$( ${ECHO} "${OPT_LIST}" | ${WC} -w )
      COUNTER=0
      for PARAM in ${OPT_LIST}; do
          let "COUNTER = $COUNTER + 1"
          CURRENT=$( ${GREP} "^${PARAM}=" ${TMPFILE} | ${CUT} -d= -f2 )
          if [ "${COUNTER}" -lt "${NUM_PARAMS}" ]; then
             ${ECHO} -e "${CURRENT}${DELIM}\c"
          else
             ${ECHO} -e "${CURRENT}\c"
          fi
      done
      > ${TMPFILE}
      ${ECHO}
   done
}

#
# main()
#

FULL_CMD_LIST="$@"
while getopts ":cpPrsv" OPTION; do
   case ${OPTION} in
      "c"   ) CSV_MODE=1
              ;;
      "p"   ) PKG_NAME=1
              ;;
      "P"   ) FULL_PKG_NAME=1
              ;;
      "r"   ) REL_NUM=1
              ;;
      "s"   ) SUMMARY=1
              ;;
      "v"   ) VER_NUM=1
              ;;
      *     ) print_usage
              exit ${ERROR}
              ;;
   esac
done
shift $(( ${OPTIND} - 1 ))

if [ "${PKG_NAME}" -eq "0" -a "${FULL_PKG_NAME}" -eq "0" -a "${REL_NUM}" -eq "0" -a "${SUMMARY}" -eq "0" -a "${VER_NUM}" -eq "0" ]; then
   print_error "At least one information option must be specified"
   exit "${ERROR}"
fi

check_os
get_rpm_info
cleanup

exit ${SUCCESS}