#!/bin/sh

#======================================================================
#
#  Contributor:
#
#    James A. Puzzo, Digi International, Inc.  (jamesp@digi.com)
#
#======================================================================

VERSION="1.0.2"

#======================================================================
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.
# 
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
#  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#  PURPOSE.  See the GNU General Public License for more details.
# 
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#======================================================================

#======================================================================
#
# digirpm
#
#   This tool is intended to allow the ignorant user to quickly
#   generate and install a binary RPM from a source RPM as
#   distributed by Digi International, Inc.  The source could
#   easily be modified to be more general, if necessary.
#
#   It is assumed that the source RPM name will take the form
#      <stuff>-<v>-<r>.src.rpm
#
#   It is assumed that the SPEC file will take one of the following
#   forms (checked in this order):
#
#      <stuff>-<v>-<r>.spec
#      <stuff>-<v>.spec
#      <stuff>.spec
#
#   It is assumed that the binary RPM name will take the form
#      <stuff>-<v>-<r>.<arch>.rpm
#
#   <v> and <r> are strings which contain any combination of numbers,
#   letters, or periods.
#
#======================================================================

usage() {
	cat <<EOF
Version: ${VERSION}

Usage:

   $0 [options] <file>

   The intent of the tool is to streamline the procedure necessary
   to install a package beginning with a source RPM.  There are four
   steps associated with this process:

      1. copy the source RPM file to an appropriate directory for
         manipulation
      2. extract the source code from the RPM file to an appropriate
         location
      3. create a binary RPM unique to the system being operated upon
         and place this RPM in an appropriate location
      4. install the package from the binary RPM

   This revision of the tool assumes that you have a "/usr/src/redhat"
   directory tree, including the following directories: "SRPMS",
   "SPECS", BUILD", "SOURCES", and "RPMS".  These directories are chosen
   as the "appropriate" location for many of the intermediate files.

   This revision of the tool requires that the filename supplied
   end in ".src.rpm".

   A log file will be created (by default digirpm.log) to allow one
   to debug failure modes, if they occur.  The output of the RPM
   commands which generate the intermediate files will be available
   in the log file.

Options:

   General Options:
      -h         View the usage
      -V         Display version

   Control Options:
      -e <num>   Will stop the process after step <num>, as defined
                 above.  The default is "4", i.e. the complete process.
      -u         Requires the "wget" tool to be in the path.  If "wget"
                 is available, <file> will be treated as a URL and
                 "wget" will be used to "download" the file to the
                 system.

   Feedback Options:
      -l <file>  Use <file> for the logfile, rather than digirpm.log
      -v         Send more verbose information about the RPM operations
                 to the logfile
      -q         Don't display any progress or error messages.  The 
                 \$? status will indicate success or failure.  The log
                 file will still be produced.
      -qq        Like "-q", but also will not produce a log file
EOF
	exit 1
}


#
#  Intended to verify the existence of a command in the
#  path, and to error out otherwise.  Tested before any
#  operations occur.
#
chkcmd() {
	cmd="$1"

	res=`which ${cmd} 2>&1`

	if [ $? -ne 0 ]
	then
		echo "Error: $res" >&2
		echo "Couldn't find command \"${cmd}\" in path." >&2
		exit 1
	fi
}


#
#  Intended to verify the existence of a directory, and
#  to error out otherwise.  Tested before any operations
#  occur.
#
chkdir() {
	dir="$1"

	if [ \! -d ${dir} ]
	then
		echo "Error:" >&2
		echo "Couldn't find directory \"${dir}\"." >&2
		exit 1
	fi
}


#
#  Intended to verify the existence of a directory, and
#  to attempt to creat it otherwise.  Tested before any
#  operations occur.
#
chkmkdir() {
	dir="$1"

	if [ \! -d ${dir} ]
	then

		res=`mkdir -p ${dir} 2>&1`

		if [ $? -ne 0 ]
		then
			echo "Error: $res" >&2
			echo "Couldn't create directory \"${dir}\"." >&2
			exit 1
		fi
	fi
}


#
#  echo to logfile, screen, or neither, depending on
#  QUIETLEVEL:  0 - both logfile and screen, 1 - only
#  logfile, >1 - neither
#
logecho() {
	if [ ${QUIETLEVEL} -eq 0 ]
	then
		echo "$*" | tee -a ${LOGFILE}
	elif [ ${QUIETLEVEL} -eq 1 ]
	then
		echo "$*" >> ${LOGFILE}
   fi
}


#
#  Step 1 processing.  Copy file (or URL) to SRPMDIR
#
step1() {
	logecho "Starting step 1."

	if [ ${URL} -gt 0 ]
	then
		if [ -e ${SRPMDIR}/${SRPMNAME} ]
		then
			rm -f ${SRPMDIR}/${SRPMNAME}
		fi

		tmp=`which wget 2>&1`
		if [ $? -ne 0 ]
		then
			logecho "  The \"wget\" tool was not in the path."
			logecho "  URL sources are not supported without it."
			exit 1
		fi
		res=`wget -q -O ${SRPMDIR}/${SRPMNAME} ${SOURCEFILE} 2>&1`
		if [ $? -ne 0 ]
		then
			logecho "  Error: ${res}"
			logecho "  Couldn't get ${SOURCEFILE}."
			exit 1
		fi
	else
		diff ${SOURCEFILE} ${SRPMDIR}/${SRPMNAME} 1>/dev/null 2>&1
		if [ $? -eq 0 ]
		then
			touch ${SRPMDIR}/${SRPMNAME}
		else
			if [ -e ${SRPMDIR}/${SRPMNAME} ]
			then
				rm -f ${SRPMDIR}/${SRPMNAME}
			fi

			res=`cp ${SOURCEFILE} ${SRPMDIR}/${SRPMNAME} 2>&1`
			if [ $? -ne 0 ]
			then
				logecho "  Error: ${res}"
				logecho "  Couldn't get ${SOURCEFILE}."
				exit 1
			fi
		fi
	fi

	logecho "  ${SRPMNAME} has been copied."
	logecho "Step 1 complete."
}


#
#  Step 2 processing.  Extract the source files.
#
step2() {
	logecho "Starting step 2."

	rpm -i ${VEROPT} ${SRPMDIR}/${SRPMNAME} 1>>${LOGFILE} 2>&1 
	if [ $? -ne 0 ]
	then
		logecho "  Error:"
		logecho "  Couldn't extract source from ${SRPMNAME}"
		exit 1
	fi

	logecho "  Source files from ${SRPMNAME} extracted."
	logecho "Step 2 complete."
}


#
#  Step 3 processing.  Build the binary RPM.
#
step3() {
	logecho "Starting step 3."

	b1="${BASENAME}"
	b2=`expr "${BASENAME}" : '\(.*\)-[0-9a-zA-Z.]*'`
	b3=`expr "${BASENAME}" : '\(.*\)-[0-9a-zA-Z.]*-[0-9a-zA-Z.]*'`

	specfile=`find ${SPECDIR} -name "${b1}.spec" -print | head -1`
	if [ "x${specfile}x" = "xx" ]
	then
		specfile=`find ${SPECDIR} -name "${b2}.spec" -print | head -1`
		if [ "x${specfile}x" = "xx" ]
		then
			specfile=`find ${SPECDIR} -name "${b3}.spec" -print | head -1`
		fi
	fi

	if [ "x${specfile}x" = "xx" ]
	then
		logecho "  Error:"
		logecho "  Can't find RPM specification file.  Tried:"
		logecho "    ${b1}.spec"
		logecho "    ${b2}.spec"
		logecho "    ${b3}.spec"
		exit 1
	fi

	rpm -bb ${VEROPT} ${specfile} 1>>${LOGFILE} 2>&1
	if [ $? -ne 0 ]
	then
		logecho "  Error:"
		logecho "  Couldn't build RPM using ${specfile}"
		exit 1
	fi

	logecho "  Binary RPM distribution has been built from ${specfile}."
	logecho "Step 3 complete."
}


#
#  Step 4 processing.  Install package from binary RPM.
#
step4() {
	logecho "Starting step 4."

	rpmfile=`find ${RPMDIR} -name "${BASENAME}.*.rpm" \
	               -newer ${SRPMDIR}/${SRPMNAME} -print | head -1`

	if [ "x${rpmfile}x" = "xx" ]
	then
		logecho "  Error:"
		logecho "  Can't find binary RPM file."
		exit 1
	fi

	rpm -i ${VEROPT} ${rpmfile} 1>>${LOGFILE} 2>&1
	if [ $? -ne 0 ]
	then
		logecho "  Error:"
		logecho "  Couldn't install RPM from ${rpmfile}"
		exit 1
	fi

	logecho "  Distribution has been installed from ${rpmfile}."
	logecho "Step 4 complete."
}


#======================================================================
#   MAIN
#======================================================================
#
#  Initialize variables
#
FINALSTEP=4
QUIETLEVEL=0
VERBOSITY=0
URL=0
LOGFILE="./digirpm.log"

SOURCEFILE=""

BASENAME=""
SRPMNAME=""

SRPMDIR="/usr/src/redhat/SRPMS"
RPMDIR="/usr/src/redhat/RPMS"
SRCDIR="/usr/src/redhat/SOURCES"
SPECDIR="/usr/src/redhat/SPECS"
BLDDIR="/usr/src/redhat/BUILD"


#
#  Verify the existence of all critical tools
#
chkcmd rpm


#
#  Verify the existence of all critical directories
#
chkdir /usr/src/redhat
chkmkdir ${SRPMDIR}
chkmkdir ${SPECDIR}
chkmkdir ${SRCDIR}
chkmkdir ${BLDDIR}
chkmkdir ${RPMDIR}


#
#  Command line parameter handling
#
set -- `getopt hVe:n:ul:vq $*`
if [ $? -ne 0 ]
then
	usage
fi

for i in $*
do
	case $i in
	-h)	usage ;;
	-V)	echo ${VERSION} ; exit 0 ;;
	--)	shift ; break;;

	-e)	FINALSTEP="$2" ;
			shift ; shift ;;
	-u)	URL=1 ;
			shift ;;

	-l)	LOGFILE="$2" ;
			shift ; shift ;;
	-v)	VERBOSITY=`expr ${VERBOSITY} + 1`
			shift ;;
	-q)	QUIETLEVEL=`expr ${QUIETLEVEL} + 1`
			shift ;;
	esac
done

if [ $# -ne 1 ]
then
	usage
fi

SOURCEFILE="$1"

if [ ${QUIETLEVEL} -ge 2 ] ;then LOGFILE="/dev/null" ;fi

if [ ${VERBOSITY} -gt 0 ]
then
	VEROPT="-vv"
else
	VEROPT=""
fi


echo "" > ${LOGFILE}
if [ $? -ne 0 ]
then
	echo "Can't open logfile : ${LOGFILE}"
	if [ ${QUIETLEVEL} -lt 2 ] ;then QUIETLEVEL=2 ;fi
fi


#
# Double-check that the sourcefile name ends in ".src.rpm"
#

testfilename=`expr "${SOURCEFILE}" : '\(.*\)\.src\.rpm$'`
if [ $? -ne 0 ]
then
	logecho "Source filename must end in \".src.rpm\""
	exit 1
fi


#
# Query the RPM to determine what the actual target filename should be
#

BASENAME=`rpm -q -p ${SOURCEFILE} 2>&1`
if [ $? -ne 0 ]
then
	logecho "Error: ${BASENAME}"
	logecho "Couldn't extract source RPM name from source file"
	exit 1
fi
SRPMNAME="${BASENAME}.src.rpm"


#
#  Execute steps
#

step1

if [ ${FINALSTEP} -eq 1 ]
then
	logecho "Operation terminated after step 1: package copy"
	exit 0
fi

step2

if [ ${FINALSTEP} -eq 2 ]
then
	logecho "Operation terminated after step 2: extract source"
	exit 0
fi

step3

if [ ${FINALSTEP} -eq 3 ]
then
	logecho "Operation terminated after step 3: build binary RPM"
	exit 0
fi

step4

logecho "Installation complete."

exit 0
