#!/usr/bin/ksh
###############################################################################
# Version: Mar 09, 2004
###############################################################################
#
# installnewer
#
#   Usage: installnewer <dir>
#       <dir> is a directory containing new RPM images
#
#   Given the RPM images installed on the system, examine the specified
#   directory for newer versions of RPMS, and install them along with any
#   new prerequisite packages.
#
#   LIMITATION: This script is based on the new prerequisites as of
#   Mar 09, 2004.  The dependencies are not determined dynamically,
#   so if you run this script long in the future when new dependencies
#   exist for some packages, it may not find them.  Check
#   ftp://ftp.software.ibm.com/aix/freeSoftware/aixtoolbox/contrib/installnewer
#   to see if you have the current version of this script.
#
###############################################################################
# (C) COPYRIGHT International Business Machines Corp. 2002,2003,2004
# All Rights Reserved
#
# Disclaimer:  This is an unsupported, unwarranted script provided
# for the convenience of users of the 'AIX Toolbox for Linux Applications'.
# It will automatically install RPMS onto your system.
# Use at your own risk.
#
# No Warranty:
# THIS CODE IS PROVIDED BY IBM "AS IS." TO THE EXTENT PERMITTED BY APPLICABLE
# LAW, IBM MAKES NO WARRANTIES OR CONDITIONS EITHER EXPRESS OR IMPLIED,
# INCLUDING WITHOUT LIMITATION ANY WARRANTY OF NON-INFRINGEMENT AND THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
# REGARDING THE CODE OR TECHNICAL SUPPORT, IF ANY.
#
# Limitation of Liability:
# NEITHER IBM NOR ITS SUPPLIERS ARE LIABLE FOR ANY DIRECT OR INDIRECT DAMAGES,
# INCLUDING WITHOUT LIMITATION, LOST PROFITS, LOST SAVINGS, OR ANY INCIDENTAL,
# SPECIAL, OR OTHER ECONOMIC CONSEQUENTIAL DAMAGES, EVEN IF IBM IS INFORMED OF
# THEIR POSSIBILITY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR
# LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE EXCLUSION OR
# LIMITATION MAY NOT APPLY TO YOU.
###############################################################################

LANG=C; export LANG
PATH=/usr/bin:

if [[ $# -ne 1 ]]
then
   echo "Usage: installnewer <directory>"
   echo "       Attempts to update currently installed RPMS to newer versions"
   echo "       present in the specified directory."
   echo "       If updating an RPM requires a new dependency that is not"
   echo "       currently installed, the dependency will be installed as well."
   echo
   echo "Default installation flags are -hUv.  Set RPMFLAGS to use different flags."
   echo "Set DEBUG=1 in your environment to simply see the list of RPMS that"
   echo "would be installed, without installing."
   echo
   exit 1
fi

if [[ $(id -un) != "root" ]]
then
   print -u2 "Sorry, you must be root to install the RPM images"
   exit 1
fi

lslpp -l rpm.rte >/dev/null 2>&1 || {
   print -u2 "You need to install rpm.rte first"
   exit 1
}

umask 022
DIR=$1
DIRLIST=/tmp/dirrpms.$$		# RPMS in the specified directory
CURLIST=/tmp/currpms.$$		# RPM info installed on the system
NEWLIST=/tmp/newrpms.$$		# out-of-date RPMS to add to system
ADDLIST=/tmp/addlist.$$		# new requisite discoveries to add
INSTALL_THESE=			# names of binary RPM files to install
unset UPDATEIMG
[[ -z "$RPMFLAGS" ]] && RPMFLAGS="-hUv"

# Remove temporary files
cleanup()
{
rm -f $DIRLIST $CURLIST $ADDLIST $NEWLIST 2>/dev/null
}

#
# Used later, for adding new dependencies to list of RPMS that
# should be installed.
#
add_if_missing()
{
for new_dep in $NEWDEP ; do
   grep "^$new_dep:" $CURLIST >/dev/null
   [[ $? -ne 0 ]] && {
     echo $new_dep >> $ADDLIST
   }
done
}

#
# Get list of available images from specified directory
#
if [[ ! -z "$DIR" ]]
then
    cd $DIR 2>/dev/null
    if [[ $? -ne 0 ]]
    then
        print -u2 "Error: could not access directory $DIR"
	exit 1
    fi
    echo "Determining RPMs available in $DIR ..."
    # Get stanza list of binary RPMS, versions, and filenames
    /bin/ls | while read pkgfile
    do
       [[ ! -f $pkgfile ]] && continue
       pkg=`rpm -q --queryformat '%{NAME}:%{VERSION}-%{RELEASE}\n' -p $pkgfile \
            2>/dev/null`
       [[ -n "$pkg" ]] && {
	  echo $pkg:$pkgfile
       }
    done > $DIRLIST
fi

if [[ ! -s $DIRLIST ]] ; then
    print -u2 "No readable RPM images were found in $DIR"
    cleanup
    exit 8
fi

#
# Get list of versions installed on system currently
#
print -u2 "Cataloging RPMs installed on system..."
rpm -q --queryformat '%{NAME}:%{VERSION}-%{RELEASE}\n' -a >  $CURLIST
if [[ ! -s $CURLIST ]] ; then
    print -u2 "No RPMS could be found installed on system."
    cleanup
    exit 8
fi

print -u2 "Determining packages which should be installed..."
for curimage in $(cat $CURLIST) ; do
    IMGname=$(echo $curimage | awk -F ":" '{print $1}')
    IMGvers=$(echo $curimage | awk -F ":" '{print $2}')

    #
    # See if the image on the system matches the same level
    #
    DIRENTRY=$(grep "^$IMGname:" $DIRLIST)
    if [[ -n "$DIRENTRY" ]]; then
	# We have a matching file.  See if version is same.
        CDvers=$(echo $DIRENTRY | awk -F ":" '{print $2}')
        if [[ "$IMGvers" != "$CDvers" ]]; then
	   # This entry is out of date.  Add to the list.
           addname=$(echo $DIRENTRY | awk -F ":" '{print $1}')
	   UPDATEIMG="$UPDATEIMG $addname"
	   echo $addname >> $NEWLIST
        fi
    else
        # Check special cases, where name won't match newer version.
	case $IMGname in
	   bash2)  # has been renamed just "bash"; see if that is there
		DIRENTRY=$(grep "^bash:" $DIRLIST)
		if [[ -n "$DIRENTRY" ]]; then
		   addname=$(echo $DIRENTRY | awk -F ":" '{print $1}')
		   UPDATEIMG="$UPDATEIMG $addname"
		   echo $addname >> $NEWLIST
		fi
		;;
	   lclint)  # has been renamed to "splint"; see if that is there
		DIRENTRY=$(grep "^splint:" $DIRLIST)
		if [[ -n "$DIRENTRY" ]]; then
		   addname=$(echo $DIRENTRY | awk -F ":" '{print $1}')
		   UPDATEIMG="$UPDATEIMG $addname"
		   echo $addname >> $NEWLIST
		fi
		;;
	esac
    fi
done

if [[ ! -s $NEWLIST ]] ; then
    echo "All images installed are current relative to $DIR contents."
    cleanup
    exit 0
fi

#
#  Find all NEW dependencies for packages that at one time did not
#  have a dependency on said package (at any time -- not necessarily
#  a "new" requirement)
#  Reflects dependencies added anytime since "first Toolbox appearance"
#  of each package.
#  This is a little tricky.  We have to check on dependencies of dependencies,
#  in case they may not be installed either.  We will check that, and only
#  add if not installed.  (If installed and out-of-date, we already discovered
#  it, so it is OK that we are not adding it to the list again; that is why
#  add_if_missing checks against the currently installed list).
#  This is created manually and is thus prone to omissions.
#  You may instead wish to use the "update_tbox" script.
#
print -u2 "Identifying new RPM dependencies..."
for imagename in $(cat $NEWLIST) ; do
   # Add new dependencies (some may be installed anyway)
   case $imagename in
	   ImageMagick)
	       NEWDEP="bzip2 freetype libjpeg libpng libtiff zlib gettext"
	       NEWDEP="$NEWDEP libxml2 freetype2"
		add_if_missing
	       ;;
	   MySQL)
	       NEWDEP="coreutils gettext"
		add_if_missing
	       ;;
	   ORBit2)
	       NEWDEP="libIDL"
		add_if_missing
	       ;;
	   a2ps)
	       NEWDEP="info bash"
		add_if_missing
	       ;;
	   aalib-devel)
	       NEWDEP="aalib"
		add_if_missing
	       ;;
	   apache)
	       NEWDEP="expat openssl"
		add_if_missing
	       ;;
	   control-center)
	       NEWDEP="esound popt pango metacity gettext gtk2 glib2 gnome-vfs2"
	       NEWDEP="$NEWDEP libgnomeui gnome-desktop libgnome libglade2"
	       NEWDEP="$NEWDEP GConf2 libbonoboui libbonobo libgnomecanvas atk"
	       NEWDEP="$NEWDEP ORBit2 libIDL xscreensaver startup-notification"
		add_if_missing
	       ;;
	   emacs-X11)
	       NEWDEP="Xaw3d libjpeg libpng libtiff libungif coreutils"
	       NEWDEP="$NEWDEP gettext"
		add_if_missing
	       ;;
	   gawk|gimp-libgimp|gmc|indent|mc|trueprint|vim-X11|vim-enhanced)
	       NEWDEP="gettext"
		add_if_missing
	       ;;
	   gimp)
	       NEWDEP="aalib gettext gnome-libs zlib"
	       NEWDEP="$NEWDEP ORBit audiofile db esound imlib libugif"
		add_if_missing
	       ;;
	   gnome-desktop)
	       NEWDEP="atk libgnomecanvas startup-notification"
		add_if_missing
	       ;;
	   gnome-libs)
	       NEWDEP="audiofile db esound"
		add_if_missing
	       ;;
	   gnome-utils)
	       NEWDEP="popt pango gnome-panel gettext gtk2 glib2 gnome-vfs2 atk"
	       NEWDEP="$NEWDEP libgnomeui libgnome GConf2"
	       NEWDEP="$NEWDEP libbonobo atk ORBit2 scrollkeeper libIDL"
		add_if_missing
	       ;;
	   gnome-vfs2)
	       NEWDEP="gnome-mime-data"
		add_if_missing
	       ;;
	   gtk2)
	       NEWDEP="atk"
		add_if_missing
	       ;;
	   icewm)
	       NEWDEP="glib"
		add_if_missing
	       ;;
	   kdebase)
	       NEWDEP="openssl prngd xpm"
		add_if_missing
	       ;;
	   kdegames)
	       NEWDEP="arts"
		add_if_missing
	       ;;
	   kdelibs-sound)
	       NEWDEP="audiofile arts"
		add_if_missing
	       ;;
	   kdelibs)
	       NEWDEP="audiofile libxml2 openssl pcre prngd arts libxslt"
		add_if_missing
	       ;;
	   koffice)
	       NEWDEP="python expat db gdbm"
		add_if_missing
	       ;;
	   libbonoboui)
	       NEWDEP="atk libart_lgpl libgnomecanvas"
		add_if_missing
	       ;;
	   libglade2)
	       NEWDEP="atk"
		add_if_missing
	       ;;
	   libgnomeui)
	       NEWDEP="atk libart_lgpl libgnomecanvas"
		add_if_missing
	       ;;
	   libpng-devel|php|freetype2)
	       NEWDEP="zlib"
		add_if_missing
	       ;;
	   lynx)
	       NEWDEP="openssl"
		add_if_missing
	       ;;
	   metacity)
	       NEWDEP="startup-notification"
		add_if_missing
	       ;;
	   pango)
	       NEWDEP="fontconfig"
		add_if_missing
	       ;;
	   python)
	       NEWDEP="db expat"
		add_if_missing
	       ;;
	   qt-devel)
	       NEWDEP="libmng libjpeg zlib"
		add_if_missing
	       ;;
	   qt)
	       NEWDEP="libmng libungif"
		add_if_missing
	       ;;
	   rep-gtk)
	       NEWDEP="gdk-pixbuf libglade imlib gnome-libs libjpeg libpng"
	       NEWDEP="$NEWDEP libtiff ORBit audiofile db esound"
		add_if_missing
	       ;;
	   tkinter)
	       NEWDEP="tcl tk"
		add_if_missing
	       ;;
	   transfig)
	       NEWDEP="libpng gettext zlib"
		add_if_missing
	       ;;
	   xfig)
	       NEWDEP="libpng zlib"
		add_if_missing
	       ;;
	   xscreensaver)
	       NEWDEP="libjpeg libxml2 pango gettext gtk2 glib2 libglade2 atk"
		add_if_missing
	       ;;
   esac

done   # for imagename in NEWLIST

#Remove duplicates
[[ -s $ADDLIST ]] && CHECKADD=$(sort -u $ADDLIST)

# Now, do any of these new packages not exist in the specified directory?
# If so, the install will fail
if [[ ! -z "$CHECKADD" ]]; then
 for image in $CHECKADD ; do
   grep "^$image:" $DIRLIST >/dev/null
   [[ $? -ne 0 ]] && {
       print -u2 "error: an updated package requires $image, which was not"
       print -u2 "  found in the specified install directory"
       cleanup
       exit 2
   }
   # The new image is available; add to the list
   echo $image >> $NEWLIST
 done
fi

# At this point, $NEWLIST contains all the RPMS that need to be installed.
# Convert them to their binary package names (in $INSTALL_THESE).
if [[ ! -s $NEWLIST ]] ; then
    echo "There are no new RPMS to install."
    cleanup
    exit 0
fi

for image in $(sort -u $NEWLIST); do
    DIRENTRY=$(grep "^$image:" $DIRLIST)
    [[ -n "$DIRENTRY" ]] && {
      addfile=$(echo $DIRENTRY | awk -F ":" '{print $3}')
      INSTALL_THESE="$INSTALL_THESE $addfile"
    }
done

if [[ -n "$INSTALL_THESE" ]]
then
      if [[ -n "$DEBUG" ]]
      then
	# DEBUG set; just list the images
        print -u2 "The following RPMS would be installed"
        echo $INSTALL_THESE | tr ' ' '\n'
      else
        print -u2 "Invoking rpm..."
        rpm $RPMFLAGS $INSTALL_THESE
	if [[ $? -ne 0 ]]; then
          print -u2 "An unexpected error occurred.  Try running this script"
          print -u2 "again with DEBUG=1 to see what RPMS we are trying to"
          print -u2 "install.  If the error is not evident, you may want"
          print -u2 "to use the RPM list produced as a basis for installing"
          print -u2 "the images on our own."
          cleanup
          exit 3
          fi
      fi
else
      print -u2 "$0: No newer RPMs in $DIR were found."
fi

cleanup
exit 0
# END OF SCRIPT
