#!/bin/sh
#
# $Id: GetApplyPatch,v 1.22 2001/01/19 19:40:28 reggers Exp $
#
# Get and apply a patch from Sunsolve. In combination with CheckPatches
# you ought to be able to manage your patches a bit better.
#
# Usage: 
#	GetApplyPatch patch-no [patch-no ...]
# or	CheckPatches | sort -u | GetApplyPatch
#
# CAVEAT EMPTOR: This software is made available AS IS with no assurance
#		of fitness. No guarantee is given or implied. Nor should
#		any be assumed. Use at your own risk!!
#
# v 1.17 -- Sean Boran <sean@boran.com> adds $user. In combination with
#           $site you can get through an ftp proxy to reach sunsolve.
#
# eg.  GetApplyPatch -s proxy.company.com -u anonymous@sunsolve.sun.com ..etc
#
# Reg Quinton <reggers@ist.uwaterloo.ca>; 2-Jul-1999

umask 022
PATH=/usr/bin:/bin:/usr/sbin; export PATH
Usage='GetApplyPatch [ -b ][ -s site ][ -u user ][ -d directory ][ PatchNo ....]
     -b             batch mode, no questions asked.
     -s site        anon-ftp site (default: sunsolve.sun.com
     -u user        anon-ftp user (default: ftp
     -d directory   directory at anon-ftp site (default: /pub/patches
     PatchNo        patch number (default: stdin patchreport)'

# default site and directory. My name for anon-ftp to the site

site=sunsolve.sun.com			# where to get patches
patches=/pub/patches			# which directory to find them
user=ftp				# the "anonymous" account
pass=$LOGNAME@`hostname`		# for anon-ftp login
SunOS=`uname -r`			# different tricks for releases

# where I work, clean up when you're done

Tmp=/tmp/GetApplyPatch.$$
	rm -rf "$Tmp"; mkdir "$Tmp"; cd "$Tmp"
	trap "cd /tmp; rm -rf $Tmp 2>/dev/null" 0 1 2 3 13 15

# in batch mode I barrel through with no questions asked

BATCH=true
( tty -s </dev/tty ) >/dev/null 2>&1 && BATCH=false

# fatal error -- moan and die 

die () {
  echo "$*" 1>&2 ;  exit 255
}

# drag a file over using anon-ftp

Fetch () {
  echo "Fetching ftp://$site$patches/$1 ..."
  ftp -n -i $site <<EOF
user $user $pass
type binary
cd $patches
get $1
EOF
   [ -r "$1" ] && return 0
   return 255
}

# Get and unpack a patch

GetPatch() {
  if [ "$1" != "`expr "$1" : '^\([0-9]\{6\}-[0-9]\{2\}\)'`" ]; then
 	echo 1>&2 "ERROR: $1 is not a patch number ...";  return 127
  fi
  case $SunOS in
    5.[8]*)
	if Fetch $1.zip && unzip $1 >/dev/null; then
		rm $1.zip; return 0
	fi
	;;
    5.[7]*)	# transitional zip  files
	if Fetch $1.zip && unzip $1 >/dev/null; then
		rm $1.zip; return 0
	fi
	if Fetch $1.tar.Z && zcat $1.tar.Z | tar xf -; then
		rm $1.tar.Z; return 0
	fi
	;;
    5.[56]*)
	if Fetch $1.tar.Z && zcat $1.tar.Z | tar xf -; then
		rm $1.tar.Z; return 0
	fi
	;;
    *)	die "I don't know about patches on this OS version!"
	;;
  esac

  echo 1>&2 "ERROR: cannot get patch $1 bailing out ...";  return 127
}

# Apply a patch

PatchAdd () {
  case $SunOS in
    5.5*)     	cd $1; ./installpatch . ; cd ..
		;;
    5.[678]*)	patchadd $1
		;;
    *)		die "I don't know about applying patches on this OS version!"
		;;
  esac
}

# Get a patch and apply it

GetApply() {

  if showrev -p | awk '{print $2}' | grep '^'$1'$' >/dev/null; then
    echo 1>&2 "ERROR: $1 is already applied!";
    return 127
  fi

  # Go get it ... or fail

  GetPatch $1 || return 127

  # In batch mode we do it and clean up... period.

  if $BATCH; then
    PatchAdd $1; rm -rf $1
    return
  fi

  # let the reader decide

  echo; echo "Patch $1 retrieved from $site; README says: "
  more $1/README.$1 < /dev/tty

  echo; echo "Apply $1? [y/n]" '\c'; read ans </dev/tty

  [ "$ans" = "y" ] && PatchAdd $1 </dev/tty
  [ "$ans" = "q" ] && exit 0

  # let the reader decide:

  echo; echo "Cleanup $1? [y/n]" '\c'; read ans </dev/tty

  [ "$ans" = "y" ] && rm -rf $1
  [ "$ans" = "q" ] && exit 0
}

######## Main flow starts here ######################
# parse command line options 

while getopts bhs:u:d: c; do
    case $c in
	b) BATCH=true ;;
        s) site=$OPTARG ;;
        u) user=$OPTARG ;;
        d) patches=$OPTARG ;;
        *) die "$Usage";;
    esac
done

shift `expr $OPTIND - 1`

# If I have arguments they're patches you want me to apply

if [ "$1" ]; then
  while [ "$1" ]; do
    GetApply "$1"; shift;
  done
  exit 0
fi

# Otherwise, assume a CheckPatches report on stdin

while read X; do
  PATCH=`expr "$X" : '^\([0-9]\{6\}-[0-9]\{2\}\)'`
  if [ "$PATCH" ]; then
    echo "***************** Recommended Patch *****************"
    echo "$X"
    if $BATCH; then
      GetApply $PATCH
    else
      echo "Get/Examine? [y/n]" '\c'; read ans </dev/tty
      [ "$ans" = "y" ] && GetApply $PATCH
      [ "$ans" = "q" ] && exit 0
    fi
  fi
done

exit 0

