#!/bin/bash 

###############################################################################
# Program: altertrack (alternate slacktrack)
# Purpose: Tracking & building packages for Slackware v9.1+ 
#          Inspired by Patrick Volkerding's 'bp' script
#
#          This DOES NOT USE installwatch!
#          This WILL INSTALL THE PACKAGE ON THE SYSTEM (but it updates the
#          /var/log/packages database so that you may remove it).
#          
#          DO NOT USE THIS ON ANYTHING BUT A PACKAGE BUILDING DEV BOX 
#   
#          You MUST consult the FAQ before using this script so that you avoid
#          including unrelated files in your packages.
# 
# Author : Stuart Winter <stuart@polplex.co.uk>
# Date...: 08-May-2005
# Version: 1.19
###############################################################################
# Notes:
#  [1] Notice how in the slacktrack-examples archive I make extensive use
#      of ${SLACKTRACKFAKEROOT} in the .build scripts ?
#      This environment variable is pretty useless for alterslack whilst
#      doing post install stuff (eg fixing up man pages and hardlinks)
#      within the main .build script.
#      However, it *is* useful if you want to use a post installation script
#      (via -R, --run-after) to tidy up any symlinks or other stuff you 
#      couldn't have easily done whilst still working within the root 
#      file system.
#      ${SLACKTRACKSCRATCHDIR} will still be useful to you
#
#  [2] You will more than likely have to removepkg <packagename> first.  
#      This is because unless certain files have changed from last time, 
#      they won't get reinstalled by make install and they will 
#      NOT APPEAR IN THE PACKAGE.
#      protopkg has this 'feature' also.  The only way to avoid this would be
#      to either use slacktrack or do what 'bp' does and touch all the
#      files on the file system first.  I'd rather use removepkg and
#      check the output to ensure it has removed everything it should.
#      * However, using removepkg can be DANGEROUS if you remove a package
#      that the system relies upon.  Please see question 5 of the FAQ *
################################################################################

# Program name
PROGNAME="altertrack"

# Version
SLACKTRACKVERSION="${PROGNAME} v1.19(1.26-slacktrack) by Stuart Winter <stuart@polplex.co.uk>"

# Path to Slackware's makepkg
MAKEPKG=/sbin/makepkg

# Set defaults. These may be modified via the command line switches
unset SLACKWAREPACKAGE PACKAGEDEPEND
CREATESYMLINKS=Yes
SETROOTOWNER=No
CHOWNBINDIRSROOTBIN=No
CHOWNBINFILESROOTBIN=No
TIDYONFINISH=Yes
GZMAN=No
GZINFO=No
GZMANFIXSYMLINKS=Yes
GZINFOFIXSYMLINKS=Yes
DELETEUSRINFODIR=No
STRIPPROG="$( which strip )"
STRIPLIB=No
STRIPBIN=No
STRIPALLEXEC=No
STRIPARCHIVES=No
CREATEDESCRIPTION=No
CHMODNOGLOBALWRITE=No
CHMOD644DOCS=No
BUILDSTORE=/tmp/built-slackwarepackages/ # if that dir doesn't exist it'll use /tmp
LOGGING=Yes
CREATEMD5SUM=No
SIGNPACKAGE=No
SIGNINGKEY=
NOUSRTMP=No
LOGHARDLINKS=Yes
SLACKTRACKLOGFILE="/var/tmp/$$.$(date +%s).${RANDOM}.slacktrack.log"
MANDIR_LIST="/usr/man /usr/local/man /usr/X11R?/man /opt/kde/man"
INFODIR_LIST="/usr/info /usr/local/info"
LIBDIR_LIST="/usr/lib /lib /usr/local/lib"
BINDIR_LIST="/bin /sbin /usr/sbin /usr/bin /usr/local/bin /usr/local/sbin /usr/X11R?/bin"
ROOTDIR=/
USEFAKEROOT=No
RUNCMDAFTER=
MAKEPKGOPTS=
SHOWDEPS=No
# Below is the list of files and directories that should be excluded from the list
# of files that have changed since before and after the build.
# It's in egrep's pattern format.  Note that when this string is used in altertrack,
# we prefix everything with ^ meaning to only remove the listed value if it is
# at the start of a line.  Eg, /var/log/monkey.log would be removed from the list
# (because /var/log is listed below), but /usr/monkey/var/log/monkey.log would not.
EXCLUDE_LIST="/sys$|/sys/|/initrd$|/initrd/|/dev/vc$|/dev/vc/|/dev/console|/dev/pts$|/dev/pts/|/dev/ptmx|/dev/tty|/var/log|/etc/mtab|/etc/ld.so.cache|/tmp|/root|/proc|/var/tmp|/var/run/utmp"

# Basic sanity checks
if [ ! -f "${MAKEPKG}" ]; then
   echo "ERROR: Unable to locate the Slackware 'makepkg' program"
   echo "       Your system is broken.  makepkg is part of the pkgtools"
   echo "       package; I suggest you install it"
   exit 4
fi
if [ ! -d /var/log/packages -o ! -d /var/log/scripts ]; then
   echo "ERROR: Unable to find at least one of the package"
   echo "       information repositories.  Your system is broken."
   exit 4
fi


############################################### Functions###################################
function display_usage () {
printf "Usage: ${PROGNAME} [options] -p <package_file_name> <command_line>\n"
if [ ! -z "$1" ]; then
   echo "Use $( basename $0 ) --help for a list of options"
fi
}

function display_help () {
printf "${SLACKTRACKVERSION}\n\n$(display_usage)

Startup:
 -h,   --help                   Display this help
 -v,   --version                Display version information

Options to Slackware's 'makepkg':
 -p,  --package <package_name>  Resulting tar file name of the package
 -s,  --nosymlinks              Do not create symlinks via install/doinst.sh script
 -r,  --setrootowner            Set permissions on directories to 755 and owners to root.root
      --mpopts \"<options>\"      Specify additional options to 'makepkg'

Specific altertrack options:
 -t,  --notidy                  Do not delete temporary package directory
 -b,  --buildstore <directory>  Location to store built packages
                                [ default: ${BUILDSTORE} ] 
 -l,  --logfile <filename>      Path of altertrack's logfile
                                [ default: (buildstore_path)/<package_name>.log ]
 -n,  --nologging               Delete log file upon altertrack completing successfully
 -D,  --md5sumtgz               Create an MD5sum file of the resulting .tgz 
 -G,  --gpg-sign [<id>]         Sign the resulting .tgz with GnuPG
 -z,  --gzman                   gzip any man pages found in known locations
 -I,  --gzinfo                  gzip any info pages found in known locations
 -Z,  --gzman-no-symfix         Do not repair broken symlinks caused by the --gzman option
                                [ default is to fix broken symlinks ]
 -F,  --gzinfo-no-symfix        Do not repair broken symlinks caused by the --gzinfo option
                                [ default is to fix broken symlinks ]
 -K,  --delete-usrinfodir       Delete package's /usr/info/dir file [default is no]
 -d,  --depend \"package1,pack2\" Ensure Slackware packages are installed before continuing
 -j,  --striplib                Strip executable ELF .so objects in the library directories
 -A,  --striparchives           Strip .a (archive) files found anywhere within the package
 -k,  --stripbin                Strip executable ELF files in the binary directories
 -S,  --stripallexec            Strip all executable ELF objects found within the package
 -c,  --createdescription       Create a slack-desc file named <package-name>.txt in 
                                the build store path
 -e,  --chown-bdirs-root-bin    Set ownerships of the standard Slackware binary directories to
                                'root:bin'.  If you use the --setrootowner option then it will
                                reset the directory permissions to root:root
 -f,  --chown-bfiles-root-bin   Set ownerships of files contained within the standard Slackware
                                binary directories to 'root:bin'
 -g,  --chmod644docs            Run chmod 644 & chown root:root on files in package's /usr/doc/
 -U,  --nousrtmp                If /usr/tmp is a symlink, delete it and its contents
 -T,  --tempdir <path>          Specify a temporary path for the package building
                                By default, altertrack will choose one in /var/tmp
 -L,  --nologhardlinks          Do not log the existence of hard links 
 -O,  --chmod-og-w              Run 'chmod -R og-w' over the package directory
 -x,  --exclude '/foo|/bar'     Supply replacement egrep pattern for dir/file exclusion
 -M,  --extra-mandir <path>     Append path to the man directory list
 -W,  --extra-infodir <path>    Append path to the info directory list
 -E,  --extra-libdir <path>     Append path to the lib directory list
 -B,  --extra-bindir <path>     Append path to the bin directory list
 -N,  --strip-prog <path>       Specify the location of the 'strip' binary.  
 -R,  --run-after <command>     Run command/script after build script finishes
 -Q,  --standard                Select options required to build a compliant Slackware package
      --showdeps                List the installed packages on which this new package depend
      --rootdir                 Change the directory that altertrack considers to be the root
                                [default: /]
      --froot                   Launch fakeroot prior to Slackware-ising the new package
      --with-scratchbox         Delete /dev and /home when working within Scratchbox

Suggested usage: ${PROGNAME} -Qp foo-1.0-i486-1.tgz ./foo.build
"
}

# Function to retrieve the package name.
# glibc-solibs-2.2-i386-1.tgz = glibc-solibs
function package_name () {
  local PACKAGENAME="$( echo $1 | rev | cut -d- -f4- | rev )"
  echo ${PACKAGENAME}
}

# Function to determine whether a supplied package name is already installed
# Returns 0 if not installed, 1 if installed.
# This function allows us to specify 'autoconf' for example, without having
# to worry about the version number installed (unless you specifically want to,
# in which case specify the version number as well - e.g. autoconf-2.54)
function is_package_installed () {
  local PACKAGENAME="$1"
  local installed_package

  # We have to go through each package like this (rather than just do if -f foobar-*
  # because otherwise packges such as glibc, glibc-solibs and so on get wildcarded
  # and things get confused.
   for installed_package in $( find /var/log/packages/${PACKAGENAME}-* -type f -printf "%f\n" 2>/dev/null ) ; do
       installed_package="$( package_name ${installed_package} )"
       if [ "${installed_package}" = "${PACKAGENAME}" ]; then
           return 1 # the package 'short' name is installed
           break
       fi
   done
return 0
}

# Check if we have any package dependencies.  This is a lame way of doing it and
# possibly proves nothing, but it saves me writing it in a few build scripts that
# would otherwise fail when they haven't got package X installed.
function check_package_dep () {
local error pack
# Change comma separated input into spaces and consider them one by one
for pack in $( echo ${1} | sed s/,/\ /g ); do
  is_package_installed "${pack}"
  if [ $? -eq 0 ]; then
     echo "${PROGNAME}: dependency Slackware package '${pack}' not installed"
     error=y
  else
     echo "${PROGNAME}: dependency Slackware package '${pack}' is installed. OK!"
  fi
done

if [ ! -z "${error}" ]; then 
   echo "Error: Package dependencies failed"
   return 1
fi
}


# Function to move the temporary log file into the correct place & with the correct name.
function move_log () {
if [ "${LOGGING}" = "Yes" ]; then
   if [ -z "${USER_SLACKTRACKLOGFILE}" ]; then
      # Move /var/tmp/slacklog to /tmp/built-slackwarepackages/packagename.log
      mv -f ${SLACKTRACKLOGFILE} "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).log" > /dev/null 2>&1
    else
      # The user specified their own log path; rename our /var/tmp/slacklog to their's
      mv -f ${SLACKTRACKLOGFILE} ${USER_SLACKTRACKLOGFILE} > /dev/null 2>&1
   fi
  else
   # We don't want a log, so we'll just delete the /var/tmp version
   rm -f ${SLACKTRACKLOGFILE}
fi
}

# Tidy up the temporary directory (source extraction dir and pseudo root):
function tidy_workspace () {
( if [ "${TIDYONFINISH}" = "Yes" ]; then
     echo -n "${PROGNAME}: Deleting temporary directory"
     rm -rf /install/* /install > /dev/null 2>&1 # otherwise this may cause trouble for other builds
     rm -rf "${SLACKTRACKTMPPATH}"
     if [ $? -gt 0 ]; then
        echo " ... error removing" 
      else
        echo " ... done"
     fi
   else
     rm -rf /install/* /install > /dev/null 2>&1
     echo "${PROGNAME}: Temporary workspace '${SLACKTRACKTMPPATH}' will remain"
fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}
}

#############################################################################################
PARAMS="$( getopt -qn "$( basename $0 )" -o p:b:l:d:M:N:W:E:x:B:R:T:DG::nefgcsrthvzAISjkKULOZQ -l exclude:,mpopts:,tempdir:,package:,buildstore:,logfile:,depend:,extra-mandir:,extra-infodir:,run-after:,extra-libdir:,extra-bindir:,strip-prog:,nologging,createdescription,gzman,gzinfo,gzman-no-symfix,gzinfo-no-symfix,striplib,striparchives,stripbin,stripallexec,nosymlinks,nousrtmp,chmod644docs,setrootowner,chown-bdirs-root-bin,chown-bfiles-root-bin,notidy,help,version,delete-usrinfodir,nologhardlinks,md5sumtgz,gpg-sign::,chmod-og-w,standard,showdeps,rootdir:,froot,with-scratchbox -- "$@" )"

# If params are incorrect then
if [ $? -gt 0 ]; then display_help >&2 ; exit 2 ; fi
eval set -- "${PARAMS}"
for param in $* ; do
  case "$param" in

     -p|--package)           	 SLACKWAREPACKAGE="$2"
                             	 shift 2;;

     -b|--buildstore)        	 BUILDSTORE="$2/"
                             	 shift 2;;

     -l|--logfile)           	 USER_SLACKTRACKLOGFILE="$2"
                             	 shift 2;;
   
     -n|--nologging)         	 LOGGING=No
                                 shift 1;;

     -i|--install)           	 INSTALLPACKAGE="Yes"
                            	 shift 1;;

     -D|--md5sumtgz)		 CREATEMD5SUM="Yes"
				 shift 1;;

     -G|--gpg-sign)		 SIGNPACKAGE="Yes"
				 SIGNINGKEY="$2"
				 shift 2;;

     -s|--nosymlinks)        	 CREATESYMLINKS="No"
                             	 shift 1;;
 
     -U|--nousrtmp)            	 NOUSRTMP="Yes"
                             	 shift 1;;
  
     -L|--nologhardlinks)     	 LOGHARDLINKS="No"
	     	      		 shift 1;;
 
     -O|--chmod-og-w)          	 CHMODNOGLOBALWRITE="Yes"
 		           	 shift 1;;
     
     -T|--tempdir)             	 SLACKTRACKTMPPATH="$2"
			     	 shift 2;;

     -r|--setrootowner)      	 SETROOTOWNER="Yes"
                             	 shift 1;;

     --mpopts)                   MAKEPKGOPTS="$2"
				 shift 2;;
 
     -e|--chown-bdirs-root-bin)  CHOWNBINDIRSROOTBIN="Yes"
                               	 shift 1;;

     -f|--chown-bfiles-root-bin) CHOWNBINFILESROOTBIN="Yes"
                              	 shift 1;;

     -g|--chmod644docs)          CHMOD644DOCS="Yes"
                                 shift 1;;

     -t|--notidy)            	 TIDYONFINISH="No"
                             	 shift 1;;

     -c|--createdescription) 	 CREATEDESCRIPTION="Yes"
                             	 shift 1;; 

     -j|--striplib)          	 STRIPLIB="Yes"
                             	 shift 1;;

     -k|--stripbin)          	 STRIPBIN="Yes"
                             	 shift 1;;

     -S|--stripallexec)          STRIPALLEXEC="Yes"
                                 shift 1;;

     -A|--striparchives)         STRIPARCHIVES="Yes"
                                 shift 1;;

     -N|--strip-prog)            STRIPPROG="$2"
				 shift 2;;

     -z|--gzman)             	 GZMAN="Yes"
                             	 shift 1;;

     -I|--gzinfo)                GZINFO="Yes"
     				 shift 1;;
   
     -Z|--gzman-no-symfix)     	 GZMANFIXSYMLINKS="No"
  			     	 shift 1;;

     -F|--gzinfo-no-symfix)      GZINFOFIXSYMLINKS="No"
      				 shift 1;;

     -K|--delete-usrinfodir)	 DELETEUSRINFODIR="Yes"
                                 shift 1;;

     -d|--depend)            	 PACKAGEDEPEND="$2"
                             	 shift 2;;

     -x|--exclude)		 EXCLUDE_LIST="$2"
				 shift 2;;

     -M|--extra-mandir)          MANDIR_LIST="${MANDIR_LIST} $( echo ${2} | sed s/,/\ / )" # replace commas with spaces for 'for' loops
                                 shift 2;;

     -W|--extra-infodir)         INFODIR_LIST="${INFODIR_LIST} $( echo ${2} | sed s/,/\ / )" 
                                 shift 2;;

     -E|--extra-libdir)		 LIBDIR_LIST="${LIBDIR_LIST} $( echo ${2} | sed s/,/\ / )"
				 shift 2;;
 
     -B|--extra-bindir)          BINDIR_LIST="${BINDIR_LIST} $( echo ${2} | sed s/,/\ / )"
				 shift 2;;

     -R|--run-after)             RUNCMDAFTER="$2"
				 shift 2;;
    
     -v|--version)           	 printf "${SLACKTRACKVERSION}\n" ; exit 0 ;; 

     -h|--help)              	 display_help    ; exit 0 ;;

     -Q|--standard)              GZMAN="Yes"
                                 GZINFO="Yes"
                                 DELETEUSRINFODIR="Yes"
                                 STRIPALLEXEC="Yes"
                                 CREATEDESCRIPTION="Yes"
                                 CHOWNBINDIRSROOTBIN="Yes"
                                 CHOWNBINFILESROOTBIN="Yes"
                                 CHMOD644DOCS="Yes"
                                 NOUSRTMP="Yes"
				 shift ;;
    
     --showdeps)	         SHOWDEPS="Yes"
                                 shift ;;

     --froot)		         USEFAKEROOT="Yes"
                                 shift ;;


     --rootdir)			 ROOTDIR="$2"
                		 shift 2;;

     --with-scratchbox)		 WITHSCRATCHBOX=Yes
                		 shift ;;


     --) shift; break;; 
esac done

# The package name is the final argument in the list
COMMANDLINESCRIPT="$@"

# Do we have a package name & a build script ?  If not, bomb out.
if [ -z "${SLACKWAREPACKAGE}" -o -z "${COMMANDLINESCRIPT}" ]; then
   display_usage help >&2
   exit 2
fi

# Why don't we check to see if the build script exists?
# Well, if I do "/bin/sh foo.build" -- how can I check whether it exists?
# Just don't pass altertrack duff stuff ;)


# Check package dependencies
if [ ! -z "${PACKAGEDEPEND}" ]; then
   check_package_dep "${PACKAGEDEPEND}" || exit 3
fi

# Ensure the package name ends in .tgz (only a sloppy person would mess this up in their script ;) )
if [ "$( echo $SLACKWAREPACKAGE | rev | cut -d. -f1 | rev )" != "tgz" ]; then
   SLACKWAREPACKAGE="${SLACKWAREPACKAGE}.tgz"
fi


# If we didn't specify a temporary directory then we need make a random one
if [ -z "${SLACKTRACKTMPPATH}" ]; then
   SLACKTRACKTMPPATH="/var/tmp/$$.$(date +%s).${RANDOM}.slacktrack.FAKEROOT" # Temporary path for file translation
fi


# If we elected to strip everything in the entire package directory then
# set the other two strip options to something sensible to display to the
# user/log file.
if [ "${STRIPALLEXEC}" = "Yes" ]; then
   STRIPLIB="--stripallexec used, stripping all"
   STRIPBIN="${STRIPLIB}"
   STRIPARCHIVES="${STRIPLIB}"   
fi

# Let's check if user really has gpg.
if [ "${SIGNPACKAGE}" = "Yes" ]; then
   which gpg >/dev/null 2>&1 || { echo "${PROGNAME}: Warning: Cannot find gpg; disabling signature creation"; SIGNPACKAGE="No"; }
fi
	

# Display some info about the new package we're going to build
(
printf "
Package information
-------------------
Slackware package name..................: ${SLACKWAREPACKAGE}
Build script/command line...............: ${COMMANDLINESCRIPT}
Build package store.....................: ${BUILDSTORE}
altertrack log file.....................: ${SLACKTRACKLOGFILE}
altertrack temporary dir................: ${SLACKTRACKTMPPATH}
Logging.................................: ${LOGGING}
Create an MD5sum of the resulting .tgz..: ${CREATEMD5SUM} 
Sign the resulting .tgz with GnuPG......: ${SIGNPACKAGE} 
Create description file.................: ${CREATEDESCRIPTION}
Log hard links..........................: ${LOGHARDLINKS}
chmod -R og-w...........................: ${CHMODNOGLOBALWRITE}
chown root:bin binary directories.......: ${CHOWNBINDIRSROOTBIN}
chown root:bin binaries in bin dirs.....: ${CHOWNBINFILESROOTBIN}
chmod 644 & chown root:root /usr/doc/*..: ${CHMOD644DOCS}
Additional options to 'makepkg'.........: $( if [ -z "${MAKEPKGOPTS}" ]; then echo "[ None ]" ; else echo "${MAKEPKGOPTS}" ; fi )
Create Symlinks.........................: ${CREATESYMLINKS}
Set root owner..........................: ${SETROOTOWNER}
Tidy on finish..........................: ${TIDYONFINISH}
gzip man pages..........................: ${GZMAN}
gzip info pages.........................: ${GZINFO}
Fix broken gz man page symlinks.........: ${GZMANFIXSYMLINKS}
Fix broken gz info page symlinks........: ${GZINFOFIXSYMLINKS}
Delete package's /usr/info/dir page.....: ${DELETEUSRINFODIR}
Strip executable ELF binaries...........: ${STRIPBIN}
Strip executable ELF shared objects.....: ${STRIPLIB}
Strip .a (archive) files................: ${STRIPARCHIVES}
Strip all executable ELF files..........: ${STRIPALLEXEC}
Path to strip utility...................: ${STRIPPROG}
Shared objects (libraries) dirs.........: ${LIBDIR_LIST}
Binary objects dirs.....................: ${BINDIR_LIST}
Man page dirs...........................: ${MANDIR_LIST}
Info page dirs..........................: ${INFODIR_LIST}
Delete /usr/tmp symlink.................: ${NOUSRTMP}
Show dependencies to other packages.....: ${SHOWDEPS}
egrep pattern for dir/file exclusion....: ${EXCLUDE_LIST}
Command/script to run after build script: $( if [ -z "${RUNCMDAFTER}" ]; then echo "None" ; else echo ${RUNCMDAFTER} ; fi )
Directory altertrack considers is root..: ${ROOTDIR}
Use fakeroot utility whilst packaging...: ${USEFAKEROOT}
Working within Scratchbox...............: $( if [ -z "${WITHSCRATCHBOX}" ]; then echo "No" ; else echo "Yes" ; fi )
....................................................................\n"
) 2>&1 | tee ${SLACKTRACKLOGFILE}

# Delete the temporary path. Perhaps this isn't safe, but then again we're running
# on a devbox which nobody else has access to, aren't we ;)
rm -rf "${SLACKTRACKTMPPATH}" 
mkdir -pm700 "${SLACKTRACKTMPPATH}" 

# Create a temporary 'scratch' directory inside the altertrack
# temporary dir.  This is to save build scripts managing their own
# temporary directories should the author be too lazy ;)
export SLACKTRACKSCRATCHDIR="${SLACKTRACKTMPPATH}/SCRATCHDIR"
mkdir -pm700 "${SLACKTRACKSCRATCHDIR}"

export SLACKTRACKFAKEROOT="${SLACKTRACKTMPPATH}/TRANSL"
mkdir -pm755 "${SLACKTRACKFAKEROOT}" 

BEFOREFILESLIST="${SLACKTRACKTMPPATH}/before_files.list"
AFTERFILESLIST="${SLACKTRACKTMPPATH}/after_files.list"
NEWFILESLIST="${SLACKTRACKTMPPATH}/new_files.list"
DIRLIST="${SLACKTRACKTMPPATH}/dir.list"
# Generate list of files on the system prior to executing the build script
# 'bp' touches all the files on the file system.  
# The reason you *might* want to touch everything first is so that
# if mkdir /etc/package_configdir fails (because it alreasy exists)
# then the fact that it's been *tried* will be picked up
# when you scan after the build script has finished.
# However, altertrack doesn't scan like that so it wouldn't
# actually notice a thing !  
# This is the exact reason I suggest using removepkg first.
#
# I remove /mnt, /proc, /tmp and /home here to make the find
# execute more quickly.  I have a box NFS mounted on /mnt
# so it's highly undesirable to scan another OS installation
# in addition to our own ;-)
echo -n "${PROGNAME}: Finding files on the system, please wait"
( cd ${ROOTDIR} 
  find . \( -regex './\(mnt\|sys\|proc\|tmp\|home\)' -prune \) -o -not -name . -printf "%p %T@ %s\n" | cut -d. -f2- > ${BEFOREFILESLIST} ) >/dev/null 2>&1
echo " ... done"

# Launch build script with logging
if [ "${LOGGING}" = "Yes" ]; then
   ( printf "\n\n\n[$( date "+%D %r" )] ${PROGNAME}: Executing command line '${COMMANDLINESCRIPT}'\n\n"
     ${COMMANDLINESCRIPT}
     EXIT_CODE=$?
     if [ ${EXIT_CODE} -gt 0 ]; then
        printf "\n\n[$( date "+%D %r" )] ${PROGNAME}: * WARNING: ${COMMANDLINESCRIPT} returned exit code ${EXIT_CODE} *\n\n"
     fi
     printf "[$( date "+%D %r" )] ${PROGNAME}: command line '${COMMANDLINESCRIPT}' finished\n\n"
   ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}
 else
   # Launch build script without logging (allows perl's CPAN interface to work)
   ( printf "\n\n\n[$( date "+%D %r" )] ${PROGNAME}: Executing command line '${COMMANDLINESCRIPT}'\n\n"
     ${COMMANDLINESCRIPT}
     EXIT_CODE=$?
     if [ ${EXIT_CODE} -gt 0 ]; then
        printf "\n\n[$( date "+%D %r" )] ${PROGNAME}: * WARNING: ${COMMANDLINESCRIPT} returned exit code ${EXIT_CODE} *\n\n"
     fi
     printf "[$( date "+%D %r" )] ${PROGNAME}: command line '${COMMANDLINESCRIPT}' finished\n\n"
    ) 
fi


# Generate list of files post installation
# Again we miss out /mnt et al to speed up the process.
echo -n "${PROGNAME}: Finding files on the system, please wait"
( cd ${ROOTDIR}
  find . \( -regex './\(mnt\|sys\|proc\|tmp\|home\)' -prune \) -o -not -name . -printf "%p %T@ %s\n" | cut -d. -f2- > ${AFTERFILESLIST} ) >/dev/null 2>&1
echo " ... done"

# If we're running within Scratchbox then we delete /dev and /home because
# they are empty and are created by scratchbox.
if [ "${WITHSCRATCHBOX}" = "Yes" -a -f /scratchbox/scratchbox.config ]; then
   echo -n "${PROGNAME}: Scratchbox detected; deleting /dev & /home"
   rmdir ${ROOTDIR}/dev ${ROOTDIR}/home > /dev/null 2>&1
   echo " ... done"
fi

# Generate new list of files on the system (compare before and after file list)
# and delete the list of files/dirs that match the egrep pattern exclude list.
echo -n "${PROGNAME}: Comparing file lists"
diff -Bbu ${BEFOREFILESLIST} ${AFTERFILESLIST} | grep "^+" | awk '{print $1}' | cut -d+ -f2- | \
egrep -v "^(/$|\+\+$|${EXCLUDE_LIST})" > ${NEWFILESLIST}
echo " ... done"

# Remove all non-empty directories from our package contents list
# If we don't and we have any non-empty directories that have
# changed (or been accessed) then the tar (below) ends up 
# including the directory & contents in its entirety into our new package!
cd ${SLACKTRACKFAKEROOT}
echo -n "${PROGNAME}: Removing non-empty directories from package contents list"
( cd ${ROOTDIR}
  cat ${NEWFILESLIST} | while read fileline ; do
  if [ -d "./${fileline}" ]; then
     # We only retain the *empty* directories otherwise any directories
     # created by our build scripts (such as place holders) will be
     # removed.  Everything contained within the non-empty directories will
     # be picked up by tar.
     if [ "$( find "./${fileline}" | wc -l )" -ne 1 ]; then
         echo "${fileline}" >> "${DIRLIST}" 
     fi
  fi
  done ) > /dev/null 2>&1
( cat ${NEWFILESLIST} ${DIRLIST} | sort | uniq -u > ${NEWFILESLIST}.new ) > /dev/null 2>&1
mv -f ${NEWFILESLIST}.new ${NEWFILESLIST}
echo " ... done"

# Copy the changed files into our temporary package directory
echo -n "${PROGNAME}: Copying the new/changed files into temporary directory"
( cd ${ROOTDIR} ; cut -d/ -f2- ${NEWFILESLIST} | tar pvvcf - -T- | tar -C${SLACKTRACKFAKEROOT} -pxf - ) >/dev/null 2>&1
echo " ... done"

# Do we have any files in the temporary directory ?
if [ "$( find ${SLACKTRACKTMPPATH}/TRANSL -print | wc -l )" -le 1 ]; then
   ( printf "altertrack: failed to track any activity\n"
     printf "            Perhaps the build script doesn't exist or is broken\n\n"
     printf " ERROR:     Cannot build a .tgz package\n\n"
   ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}
   move_log # we will want to log this error incase we're using altertrack through an unattended auto builder
   tidy_workspace # clean up workspace
   exit 5
fi

# Launch the fakeroot utility? 
if [ "${USEFAKEROOT}" = "Yes" ]; then
   which faked >/dev/null 2>&1 || NOFAKEFOUND=yes
   if [ -z "${NOFAKEFOUND}" ]; then
      export FAKEROOTKEY="$( faked )"
      export FAKEROOTPID="$( echo ${FAKEROOTKEY} | cut -d: -f2 )"
      export FAKEROOTKEY="$( echo ${FAKEROOTKEY} | cut -d: -f1 )"
      FAKEROOT_LIB=${FAKEROOT_LIB:=/lib/libfakeroot.so.0} # you can override this by exporting it from your environment
      export LD_PRELOAD=${FAKEROOT_LIB}
      # Otherwise we leave 'faked' sitting around:
      trap "kill -s TERM ${FAKEROOTPID} >/dev/null 2>&1" EXIT INT
    else
      echo "${PROGNAME}: Warning - cannot find faked (fakeroot daemon) in $PATH; not running fakeroot"
   fi
fi

# Get back inside the package's root directory
# (we shouldn't have left it because all cding is done inside subshells
#  but it doesn't hurt)
cd ${SLACKTRACKFAKEROOT}

# Generate a list of the files that have been installed/modified on the
# file system which we use to populate the /var/log/packages/$package
# entry.  The reason we do this here rather than use the contents of the $package.tgz
# is because we modify some files (such as gzipping man pages), and as such when
# we removepkg $package, it doesn't delete /usr/man/man1/bash.1 because the entry
# would contain /usr/man/man1/bash1.gz
echo "./$( find . -printf "%P\n" )" > ${SLACKTRACKTMPPATH}/realpackagelist

# Restore original directory permissions from root filesytem.  
# Why? Because we only store (in our file list), EMPTY directories.  Example:
# I chmod 700 /etc/rc.d (which contains many startup scripts)
# My new file rc script is called 'rc.foo' and this is the only thing that's changed
# within /etc/rc.d. Therefore altertrack only preserves the file name 
# '/etc/rc.d/rc.foo', so tar has to create etc/rc.d for itself -- it has no 
# information about its permissions/ownerships.
# Why don't I just tar up the directory? read the comments above the code that does the tar.
( if [ -s ${DIRLIST} ]; then
     echo -n "${PROGNAME}: Restoring directory permissions & ownerships"
     cat ${DIRLIST} | while read line ; do
         find "${ROOTDIR}/${line}" -mindepth 0 -maxdepth 0 -printf "%U:%G" | xargs -0i chown {} "./${line}"
         find "${ROOTDIR}/${line}" -mindepth 0 -maxdepth 0 -printf "%m"    | xargs -0i chmod {} "./${line}"
     done
     echo " ... done" 
fi ) # 2>&1 | tee -a ${SLACKTRACKLOGFILE}

# gzip man pages ?
# Note that we prefix the dir name with ./ - this is so that if users specify
# additional directories with --extra-xxxdir and include / , then it doesn't actually
# *look* in the root dir.
( if [ "${GZMAN}" = "Yes" ]; then
        echo -n "${PROGNAME}: gzipping man pages"
        for man_dir in ${MANDIR_LIST}; do
            if [ -d "./${man_dir}" ]; then
	       ( find ./${man_dir} -type f -name '*.bz2' -print0 | xargs -0 bzip2 -df ) >/dev/null 2>&1
               ( find ./${man_dir} -type f -print0 | xargs -0 gzip -9   ) >/dev/null 2>&1
               ( find ./${man_dir} -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1
            fi
        done
        echo " ... done"

        if [ "${GZMANFIXSYMLINKS}" = "Yes" ]; then
          echo -n "${PROGNAME}: Fixing any broken symlinks in man page directories"
          # Fix up symlinks unless instructed not to
          for man_dir in ${MANDIR_LIST}; do
              if [ -d "./${man_dir}" ]; then 
                 ( cd ./${man_dir}
                   # Enter each man page directory (man1,man2..) and whittle them down one by one
                   for i in "$( find . -type d -maxdepth 1 -printf "%P\n" | grep -v "^$" )"; do
                       # We cd into the man dir then use find to construct some shell commands & pipe into
                       # bash for execution.  Neat huh? ;)
                       cd ${i} && ( find . -type l -printf "rm -f %P ; ln -s %l.gz %p.gz\n" ) | /bin/bash && cd ..
                   done
                 ) 
              fi
          done
          echo " ... done"
        fi
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Delete package's /usr/info/dir ?
# You're more than likely going to want to do this.
( if [ "${DELETEUSRINFODIR}" = "Yes" -a -f usr/info/dir ]; then
        echo -n "${PROGNAME}: deleting /usr/info/dir"
        rm -f usr/info/dir
        echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}

# gzip info pages ?
( if [ "${GZINFO}" = "Yes" ]; then
        echo -n "${PROGNAME}: gzipping info pages"
        for info_dir in ${INFODIR_LIST}; do
            if [ -d "./${info_dir}" ]; then
	       ( find ./${info_dir} -type f -name '*.bz2' -print0 | xargs -0 bzip2 -df ) >/dev/null 2>&1
               ( find ./${info_dir} -type f -print0 | xargs -0 gzip -9   ) >/dev/null 2>&1
               ( find ./${info_dir} -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1
            fi
        done
        echo " ... done"

        if [ "${GZINFOFIXSYMLINKS}" = "Yes" ]; then
          echo -n "${PROGNAME}: Fixing any broken symlinks in info page directories"
          # Fix up symlinks unless instructed not to
          for info_dir in ${INFODIR_LIST}; do
              if [ -d "./${info_dir}" ]; then 
                 ( cd ./${info_dir} && ( find . -type l -printf "rm -f %P ; ln -s %l.gz %p.gz\n" ) | /bin/bash ) 
              fi
          done
          echo " ... done"
        fi
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Strip shared objects ?
( if [ "${STRIPLIB}" = "Yes" ]; then
     echo -n "${PROGNAME}: Stripping unstripped ELF shared objects"
     for i in ${LIBDIR_LIST}; do 
         ( cd ./${i} && find . -name '*.so*' -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | egrep '(ELF.*shared.*not stripped)' | awk -F: '{print $1}' | xargs ${STRIPPROG} -p --strip-unneeded ) > /dev/null 2>&1
     done
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Strip .a (archive) files ?
( if [ "${STRIPARCHIVES}" = "Yes" ]; then
     echo -n "${PROGNAME}: Stripping .a (archive) files"
     ( find . -name '*.a' -type f -print0 | xargs -0 ${STRIPPROG} -p -g ) > /dev/null 2>&1
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Strip binaries?
( if [ "${STRIPBIN}" = "Yes" ]; then
     echo -n "${PROGNAME}: Stripping unstripped ELF binaries"
     for i in ${BINDIR_LIST}; do
         ( cd ./${i} && find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | egrep '(ELF.*not stripped)' | awk -F: '{print $1}' | xargs ${STRIPPROG} -p --strip-unneeded ) >/dev/null 2>&1
     done
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Strip everything?  This does the same as the above but instead it does it across
# the entire package directory -- therefore it finds stuff in /opt and anywhere else
# that files have been created.  You may prefer to use this option if you already use -jkA
# but it's worth noting that it will take longer (especially on a package with many files
# in a deep directory structure)
( if [ "${STRIPALLEXEC}" = "Yes" ]; then
  echo -n "${PROGNAME}: Stripping all unstripped executable ELF files"
  ( find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | egrep '(ELF.*not stripped)' | awk -F: '{print $1}' | xargs ${STRIPPROG} -p --strip-unneeded ) >/dev/null 2>&1
  # Strip the .a archives
  ( find . -name '*.a' -type f -print0 | xargs -0 ${STRIPPROG} -p -g ) > /dev/null 2>&1
  echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# If we find <package_builddir>/usr/tmp is a symlink then delete it.
# Some programs such as Apache seem to put stuff in here.  /usr/tmp is a symlink and is
# created by Slackware's 'aaa_base' package.  
( if [ "${NOUSRTMP}" = "Yes" -a -h "usr/tmp" ]; then
     echo "${PROGNAME}: Deleting /usr/tmp symlink from package build directory"
     rm -rf "${SLACKTRACKTMPPATH}/TRANSL/usr/tmp"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Run chmod -R og-w over the package directory ?
# In general you won't want to do this because you should take care of your
# own permissions on a per-build-script basis.  However, some software such
# as PHP leaves files globally writeable (even a recent Slackware PHP package
# had files og+w).
( if [ "${CHMODNOGLOBALWRITE}" = "Yes" ]; then
     echo -n "${PROGNAME}: Running chmod -R og-w on package contents"
     chmod -R og-w .
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Fix up ownerships in the package.  According to the 'README' that comes with
# Pat's 'slack-tools' scripts say:
# "non-setuid binaries in /bin, /sbin, /usr/bin, and /usr/sbin are
#  all chown root:bin (and the directories are, too)"
# However, I spot traceroute as being setuid and owned by root.bin
# So we'll just set everything in & including those dirs to be root.bin
# You WON'T want to always use this facility -- some build scripts such as
# 'floppy' set their own permissions correctly.  Again, you need to check over
# the .tgz afterwards and make changes to your build script accordingly.
( if [ "${CHOWNBINDIRSROOTBIN}" = "Yes" ]; then
     echo -n "${PROGNAME}: chowning root:bin the directories ${BINDIR_LIST}"
     for i in ${BINDIR_LIST}; do
         # Yes, we're assuming we may have dirs inside our bins.  I've yet to see
         # one but there may be in the future.
         ( cd ./$i && find . -type d -print0 | xargs -0 chown root:bin ) >/dev/null 2>&1
     done
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# chown root:bin files
# Please note that any additional paths specified using --extra-bindir 
# will NOT be considered here.  The Slackware standard is to only chown root:bin on
# /usr dirs -- if you look at /opt/kde/bin you'll see the files are owned by root.root
( if [ "${CHOWNBINFILESROOTBIN}" = "Yes" ]; then
     echo -n "${PROGNAME}: chowning root:bin the files inside ${BINDIR_LIST}"
     for i in ${BINDIR_LIST}; do
         ( cd ./$i && find . -type f -printf "chown root:bin '%p' && chmod %m '%p'\n" | /bin/bash ) > /dev/null 2>&1
     done
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# chmod 644 & chown root:root docs in usr/doc ?
# This is my own 'thing'.  I don't like having any executable files in
# my docs directory.
( if [ "${CHMOD644DOCS}" = "Yes" -a -d "usr/doc" ]; then
     echo -n "${PROGNAME}: Running chmod 644 over documents in usr/doc/"
     ( find usr/doc/ -type f -print0 | xargs -0 chmod 644 ) >/dev/null 2>&1
     ( chown -R root:root usr/doc/ ) >/dev/null 2>&1
     echo " ... done"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# If the user has specified both --setrootowner and --chown-bdirs-root-bin then warn
# them that their dirs permissions will be changed
# These options aren't mutually exclusive because --chown-bdirs-root-bin
# ONLY  chowns  /bin,/sbin,/usr/bin & /usr/sbin
( if [ "${CHOWNBINDIRSROOTBIN}" = "Yes" -a "${SETROOTOWNER}" = "Yes" ]; then
     echo "${PROGNAME}: * WARNING *"
     echo "  You have specified both --setrootowner AND --chown-bdirs-root-bin"
     echo "  options, but Slackware's makepkg script will change the"
     echo "  directory permissions to 'root.root'."
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}

     
# Ensure the 'root' directory of the tarchive is globally readable
# else it breaks your root dir thus your system when you install the package ;)
chmod 755 ${SLACKTRACKTMPPATH}/TRANSL
chown root:root ${SLACKTRACKTMPPATH}/TRANSL


# If the buildstore doesn't exist then we'll use /tmp instead
# We don't check this earlier because *my* scripts mkdir /tmp/built-slackwarepackages
# and Slackware's SlackBuild scripts leave the .tgz in /tmp -- and /tmp must always exist
# We won't try and create the dir because if you made a typo in the dir name, you
# make find your .tgz (that may contain sensitive files) ends up in a globally readable
# area.
if [ ! -d "${BUILDSTORE}" ]; then
   printf "altertrack: WARNING: The build store directory ${BUILDSTORE}\n"
   printf "                     does not exist; using /tmp instead\n\n"
   BUILDSTORE="/tmp/"
fi


# Show dependencies to the INSTALLED packages ?
( if [ "${SHOWDEPS}" = "Yes" ]; then
     LDDEPSFILE="${SLACKTRACKTMPPATH}/ld_list"
     LDDEPSUNRESOLVED="${SLACKTRACKTMPPATH}/ld_unresolved"
     LDDEPSFOUNDPACKAGES="${SLACKTRACKTMPPATH}/ld_found_packages"

     echo -n "${PROGNAME}: Generating list of shared library dependencies"
     # I grep out 'not found' from the list because if this package CONTAINS the
     # 'not found' library then we're not going to find it in /var/log/packages
     # This isn't the same as having what I call an 'orphaned' library.
     ( find . -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -print0 | xargs -0 file | egrep '(ELF.*shared)' | \
       awk -F: '{print $1}' | xargs ldd 2>/dev/null | grep '=>' | grep -vi 'not found' | \
       awk '{print $3}' | grep -v "^$" > "${LDDEPSFILE}" ) > /dev/null 2>&1

     # If we're running under fakeroot then remove fakeroot from
     # the dependencies.
     if [ "$( echo "${LD_LIBRARY_PATH}" | grep libfakeroot )" ]; then
        mv -f "${LDDEPSFILE}" "${LDDEPSFILE}.temp"
        grep -v "libfakeroot" "${LDDEPSFILE}.temp" > "${LDDEPSFILE}"
     fi

     if [ ! -s "${LDDEPSFILE}" ]; then
        printf "\n            Failed to find any shared object dependencies\n"
      else

        # Remove dupes from the list
        sort "${LDDEPSFILE}" | uniq > "${LDDEPSFILE}.sorted"
        mv -f "${LDDEPSFILE}.sorted" "${LDDEPSFILE}"

        # Look in /var/log/packages and /var/log/scripts (because our library
        # may be linked against a symlink) and find our packages.
        # Now, a problem that we have is that some of
        # Slackware's packages have an 'incoming' directory (eg glibc)
        # to avoid trampling over the running system without doing
        # some pokery first.
        # This is why I am *only* keeping the .so name rather than the
        # full path leading to it.
        cat "${LDDEPSFILE}" | rev | cut -d/ -f1 | rev | while read library_name ; do
            ( ( cd /var/log/packages && grep -l ${library_name} * ) || ( cd /var/log/scripts && grep -l ${library_name} * ) ) >> "${LDDEPSFOUNDPACKAGES}"
            # If we couldn't find it in a package (most likely because
            # it's linked against something that was compiled 'locally' rather than
            # being brewed into a package, or because you've broken your packages list)
            if [ $? -gt 0 ]; then
               # This way it shows the full path to the library rather than just its file name.
               egrep "${library_name}$" "${LDDEPSFILE}" >/dev/null 2>&1 && \
               echo "$( egrep "${library_name}$" "${LDDEPSFILE}" )" >> "${LDDEPSUNRESOLVED}"
            fi
        done

        # Before you think "Hold on a second old cheese, but some libraries
        # exist in more than one package (glibc/glibc-solibs is an example)
        # so what you going to do about that?"
        # Absolutely nothing! :-)  That'd mean having some sort of database
        # to know that you'd only need one of the packages listed.
        # *Also*, if you think about it, then who's to tell you whether you
        # should have glibc OR glibc-solibs? *I* only install 'glibc' because
        # I compile stuff (you don't need -solibs if you have the
        # developer/full package) .. then if I compiled this package on a box
        # that only had 'openssl' (rather than openssl-solibs *AND* openssl)
        # then... oh it's too complicated.  It's like a paradox or something.

        # Remove any dupes from the package list
        sort "${LDDEPSFOUNDPACKAGES}" | uniq > "${LDDEPSFOUNDPACKAGES}.sorted"
        mv -f "${LDDEPSFOUNDPACKAGES}.sorted" "${LDDEPSFOUNDPACKAGES}"

        # From 'generating list of dependencies' above.
        echo " ... done"

        # Dump the list of package dependencies to screen
        if [ -s "${LDDEPSFOUNDPACKAGES}" ]; then
           echo "${PROGNAME}: This package depends on libraries within the following installed packages:"
           cat "${LDDEPSFOUNDPACKAGES}" | while read line ; do
               printf "\t    ${line}\n"
           done
        fi

        # Now dump the list of dependencies into a log file.
        # We could store it somewhere in the package I suppose, any suggestions?
        install -m644 "${LDDEPSFOUNDPACKAGES}" "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).ld_deps.log"

        # And if we found any libraries that aren't part of installed packages, dump
        # those too.
        if [ -s "${LDDEPSUNRESOLVED}" ]; then
           echo "${PROGNAME}: The following libraries were not found in any installed package:"
           cat "${LDDEPSUNRESOLVED}" | while read line ; do
               printf "\t    ${line}\n"
           done
           # Not much point in listing libraries in the package if we can't
           # tell the user how to get a package containing that library, so
           # we'll just log it and let the developer fix it afterwards.
           install -m644 "${LDDEPSUNRESOLVED}" "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).orphaned_ld_deps.log"
        fi
   fi

fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Launch an external command/script before running makepkg ?
# This may be useful to inspect the package contents with a file manager such as
# Midnight Commander or xtc.
# This is extremly useful for altertrack as you can fix up symlinks and stuff
# that you couldn't do inside the root file system.
if [ ! -z "${RUNCMDAFTER}" ]; then
   echo "${PROGNAME}: Launching external command '${RUNCMDAFTER}'" >> ${SLACKTRACKLOGFILE}
   # Enter the package's root directory and run the command.  We don't log this
   # because if it's an ncurses type program then who knows what that'd do to
   # the log file.
   ( cd ${SLACKTRACKTMPPATH}/TRANSL ; ${RUNCMDAFTER} )
   echo "${PROGNAME}: External command finished" >> ${SLACKTRACKLOGFILE}
fi


# In altertrack you have no choice but to make a .tgz
# Execute the Slackware package making utility & append its output to the package logfile
( ${MAKEPKG} ${MAKEPKGOPTS} \
    --linkadd $( echo ${CREATESYMLINKS} | cut -b1 | tr A-Z a-z ) \
    --chown   $( echo ${SETROOTOWNER}   | cut -b1 | tr A-Z a-z ) \
    ${BUILDSTORE}/${SLACKWAREPACKAGE} 

  # tar up the file without compression so we can see how big it is for
  # the package description
  ( tar cf ${SLACKTRACKTMPPATH}/temp.tar . ) > /dev/null 2>&1

  # Create a package contents file for /var/log/packages
cat << EOF > /var/log/packages/"$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev )"
PACKAGE NAME: $( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev )
COMPRESSED PACKAGE SIZE: $( ls -lah ${BUILDSTORE}/${SLACKWAREPACKAGE} | awk '{print $5}' )
UNCOMPRESSED PACKAGE SIZE: $( ls -lah ${SLACKTRACKTMPPATH}/temp.tar | awk '{print $5}' )
PACKAGE LOCATION: /${SLACKWAREPACKAGE}
PACKAGE DESCRIPTION:
$( egrep -v '^($|#| *\|)' install/slack-desc 2>/dev/null )
$( cat ${SLACKTRACKTMPPATH}/realpackagelist )
EOF

  # Add the doinst.sh script into /var/log/scripts/packagename
  ( tar fOxz ${BUILDSTORE}/${SLACKWAREPACKAGE} install/doinst.sh > /var/log/scripts/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ) 
    chmod 755 /var/log/scripts/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ) ) >/dev/null 2>&1
  if [ $? -gt 0 ]; then
     rm -f /var/log/scripts/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev )
  fi

  # Delete useless .tar
  rm -f ${SLACKTRACKTMPPATH}/temp.tar

  # Warn if no slack-desc file found.  You don't need a doinst.sh script
  # though, so we won't bother with that one.
  # Why do this *after* running makepkg?  makepkg makes lots of noise
  # and unless you specifically scroll up or look at logs, you'll miss this warning.
  if [ ! -s "install/slack-desc" ]; then
     echo "${PROGNAME}: WARNING - /install/slack-desc not found or is 0 bytes"
  fi

  # Display the size of the .tgz. 
  if [ -f "${BUILDSTORE}/${SLACKWAREPACKAGE}" ]; then
     printf "${PROGNAME}: ${SLACKWAREPACKAGE}'s size is $( ls -lah ${BUILDSTORE}/${SLACKWAREPACKAGE} | awk '{print $5}' )\n"
  fi

  # Create an MD5sum of the .tgz if requested
  if [ "${CREATEMD5SUM}" = "Yes" ]; then
     echo -n "${PROGNAME}: Creating an MD5 sum of ${SLACKWAREPACKAGE}"
     ( cd "${BUILDSTORE}"
       md5sum "${SLACKWAREPACKAGE}" > "${SLACKWAREPACKAGE}.md5" )
     echo " ... done"
  fi

  # Sign the .tgz if requested to do so.
  if [ "${SIGNPACKAGE}" = "Yes" ]; then
     echo "${PROGNAME}: Signing ${SLACKWAREPACKAGE} with ${SIGNINGKEY:-your default} key"
     ( cd "${BUILDSTORE}"
       GPG_OPTIONS="--detach-sign --armor"
       if [ "${SIGNINGKEY}" ]; then
          GPG_OPTIONS="${GPG_OPTIONS} --local-user $SIGNINGKEY"
       fi

       gpg ${GPG_OPTIONS} --output ${SLACKWAREPACKAGE}.asc ${SLACKWAREPACKAGE}
       if [ $? -ne 0 ]; then
          echo "${PROGNAME}: ERROR: Signature has not been correctly generated"
        else
          echo " ... done" 
       fi )

  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Copy the slack-desc file into the build store path ?
( if [ "${CREATEDESCRIPTION}" = "Yes" -a -f "${SLACKTRACKTMPPATH}/TRANSL/install/slack-desc" ]; then
     echo "${PROGNAME}: Installing package description file into build store"
     # Cut the handy ruler, comments and empty lines out of the file.
     egrep -v '^($|#| *\|)' ${SLACKTRACKTMPPATH}/TRANSL/install/slack-desc > "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).txt"   
     chmod 644 "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).txt"
  fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}


# Log hard links
# Some packages (such as Python) use ln to create hard links rather than soft links.
# It is impossible to determine the original file name of a hard link, and thus
# must be weeded out manually.
( if [ "${LOGHARDLINKS}" = "Yes" ]; then
   echo -n "${PROGNAME}: Scanning for hard links"
   printf "$( find ${SLACKTRACKTMPPATH}/TRANSL -type f -links +1 -printf "Hard link: %P\n" )\n" > ${SLACKTRACKLOGFILE}.hardlinks 
   if [ ! -z "$( grep "Hard link:" ${SLACKTRACKLOGFILE}.hardlinks )" ]; then
      printf "\nWARNING: The following hard links were detected\n"
      cat ${SLACKTRACKLOGFILE}.hardlinks 
      echo
      # We will ALWAYS create a log file for hardlinks regardless of whether logging is disabled.
      # The packager HAS to know about them !
      mv ${SLACKTRACKLOGFILE}.hardlinks "${BUILDSTORE}/$( echo $SLACKWAREPACKAGE | rev | cut -d. -f2- | rev ).hardlinks.log"
    else
      echo " ... none found"
      rm -f "${SLACKTRACKLOGFILE}.hardlinks" 
   fi     
fi ) 2>&1 | tee -a ${SLACKTRACKLOGFILE}

# Tidy up workspace:
tidy_workspace

# Report that altertrack has finished, but to the log only.
printf "\n\n[$( date "+%D %r" )] ${PROGNAME} finished.\n"  >> ${SLACKTRACKLOGFILE}


# Unless the user has specified their own logfile, we'll use packagename-ver-arch-build.log
# If they've disabled logging with --nologging then simply delete the log file.
# You could say this was sloppy, that we're logging in the first place if we're told not to
# but given that most make scripts scroll tens of pages off the screen, I think a log file
# is *Always* handy to have, even if you don't retain it.
move_log


# Report that altertrack has finished (to screen only).
printf "\n\n[$( date "+%D %r" )] ${PROGNAME} finished.\n" 

exit 0
#EOF
