#!/bin/sh

#############################################################
# Program: slacktrack
# Purpose: Tracking & building packages for Slackware v8.1+ 
#          Based on the concepts behind 'CheckInstall'
# Author : Stuart Winter <stuart@polplex.co.uk>
# Date...: 11-Jul-2003
# Version: 1.12
#############################################################

# Program name
PROGNAME="slacktrack"

# Version
VERSION="${PROGNAME} v1.12 by Stuart Winter <stuart@polplex.co.uk>"

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

# Path to installwatch library
INSWLIB="/usr/lib/installwatch.so"

# Set defaults. These may be modified via the command line switches
unset SLACKWAREPACKAGE PACKAGEDEPEND
INSTALLPACKAGE=No
CREATESYMLINKS=Yes
SETROOTOWNER=No
CHOWNBINDIRSROOTBIN=No
CHOWNBINFILESROOTBIN=No
TIDYONFINISH=Yes
CREATESLACKWARETGZ=Yes
GZMAN=No
GZINFO=Yes
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
NOUSRTMP=No
LOGHARDLINKS=Yes
SLACKTRACKLOGFILE="/var/tmp/$$.$(date +%s).${RANDOM}.slacktrack.log"
INSTALLWATCHEXCLUDEDIRS="/tmp,/proc,/var/tmp,/usr/tmp,/dev"
MANDIR_LIST="/usr/man /usr/local/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"
RUNCMDAFTER=

# Basic sanity checks
if [ ! -f "${INSWLIB}" ]; then
   echo "ERROR: Unable to find the installwatch library"
   echo "       Your distribution of ${PROGNAME} is broken"
   exit 4
fi
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

############################################### 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 "${VERSION}\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
 
Specific slacktrack options:
 -t,  --notidy                  Do not delete temporary package directory
 -b,  --buildstore <directory>  Location to store built packages
                                [ default: ${BUILDSTORE} ] 
 -l,  --logfile <filename>      Path of slacktrack's logfile
                                [ default: (buildstore_path)/<package_name>.log ]
 -n,  --nologging               Delete log file upon slacktrack completing successfully
 -i,  --install                 Install resulting package once built
                                [ default is to not install ]
 -D,  --md5sumtgz               Create an MD5sum file of the resulting .tgz 
 -z,  --gzman                   gzip any man pages found in /usr/man and /usr/local/man
 -I,  --gzinfo                  gzip any man pages found in /usr/info and /usr/local/info
 -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]
 -x,  --exclude \"path1,path2\"   Override the default directory exclude list
 -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 in any dir within the package
 -k,  --stripbin                Strip executable ELF files in the binary directories
 -S,  --stripallexec            Strip all executable ELF objects found in the package directory
 -c,  --createdescription       Create a slack-desc file named <package-name>.txt in 
                                the build store path
 -e,  --chown-bdirs-root-bin    Set ownerships of directories /bin,/sbin,/usr/bin & /usr/sbin
                                & /usr/sbin 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 to 'root.bin' of files contained within the
                                directories /bin,/sbin,/usr/bin & /usr/sbin
 -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 installwatch module
                                By default, slacktrack will choose one in /var/tmp
 -C,  --nocreatetgz             Do not execute the Slackware 'makepkg' program
                                [ implies --notidy , default is to execute 'makepkg' ]
 -L,  --nologhardlinks          Do not log the existence of hard links 
 -O,  --chmod-og-w              Run 'chmod -R og-w' over the package directory
 -M,  --extra-mandir <path>     Append specified path to the man directory list
 -W,  --extra-infodir <path>    Append specified path to the info directory list
 -E,  --extra-libdir <path>     Append specified path to the lib directory list
 -B,  --extra-bindir <path>     Append specified path to the bin directory list
 -N,  --strip-prog <path>       Specify the location of the 'strip' binary.  
 -R,  --run-after <command>     Run specified command/script after build script finishes
"
}

# 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/,/\ / ); do
  # by wildcarding it it allows us to specify autoconf (for example) and ignore the version number (Slackware 8.1+)
  if [ ! -f /var/log/packages/${pack}* ]; 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"
    else
      # The user specified their own log path; rename our /var/tmp/slacklog to their's
      mv -f ${SLACKTRACKLOGFILE} ${USER_SLACKTRACKLOGFILE}
   fi
  else
   # We don't want a log, so we'll just delete the /var/tmp version
   rm -f ${SLACKTRACKLOGFILE}
fi
}

#############################################################################################
PARAMS="$( getopt -qn "$( basename $0 )" -o p:b:l:x:d:M:N:W:E:B:R:T:DnefgcisrthvzAISjkKUCLOZ -l tempdir:,package:,buildstore:,logfile:,exclude:,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,install,nosymlinks,nousrtmp,chmod644docs,setrootowner,chown-bdirs-root-bin,chown-bfiles-root-bin,notidy,help,version,delete-usrinfodir,nocreatetgz,nologhardlinks,md5sumtgz,chmod-og-w -- "$@" )"

# If params are incorrect then
if [ $? -gt 0 ]; then display_help ; 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;;

     -s|--nosymlinks)        	 CREATESYMLINKS="No"
                             	 shift 1;;
 
     -U|--nousrtmp)            	 NOUSRTMP="Yes"
                             	 shift 1;;

     -C|--nocreatetgz)         	 CREATESLACKWARETGZ="No"
			     	 TIDYONFINISH="No"
                             	 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;;
 
     -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)           	 INSTALLWATCHEXCLUDEDIRS="$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 "${VERSION}\n" ; exit 0 ;; 

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

     --) 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
   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 slacktrack 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


#
# Options to installwatch 
#
export INSTW_ROOTPATH=${SLACKTRACKTMPPATH}
export INSTW_TRANSL=1
export INSTW_BACKUP=0
export INSTW_LOGFILE=${SLACKTRACKTMPPATH}/installwatch.log
export INSTW_DBGLVL=1
export INSTW_EXCLUDE="${INSTALLWATCHEXCLUDEDIRS},$(pwd)" # pwd is *required*
unset  INSTW_DBGFILE


# 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}
Slacktrack log file.....................: ${SLACKTRACKLOGFILE}
Slacktrack temporary dir................: ${SLACKTRACKTMPPATH}
Logging.................................: ${LOGGING}
Install package.........................: ${INSTALLPACKAGE}
Create an MD5sum of the resulting .tgz  : ${CREATEMD5SUM} 
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}
Run Slackware 'makepkg'.................: ${CREATESLACKWARETGZ}
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}
Exclude directories.....................: ${INSTW_EXCLUDE}
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}
Command/script to run after build script: $( if [ -z "${RUNCMDAFTER}" ]; then echo "None" ; else echo ${RUNCMDAFTER} ; fi )
....................................................................\n"
) | 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 slacktrack/installwatch
# 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 the translated path.  This is very useful for some scripts
# as checkinstall does not do this, therefore I can't do certain things
# with manpages and so on.
# We can also use it to do specific file permission modification and so on.
#
# It's worth nothing that once you start fiddling in this directory,
# 'installwatch' won't detect it (unless you've changed the excluded
# directory list), which is actually what *I* want.
export SLACKTRACKFAKEROOT="${SLACKTRACKTMPPATH}/TRANSL"


# Launch the command line via installwatch & log to the logfile
( printf "\n\n\n[$( date "+%D %r" )] ${PROGNAME}: Executing command line '${COMMANDLINESCRIPT}'\n\n"
  LD_PRELOAD=${INSWLIB} ${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"
) | tee -a ${SLACKTRACKLOGFILE}


# If /var/tmp/slacktrackblah/TRANSL has no contents then we know there's been a problem.
# Even if the build script did work ok, installwatch still hasn't found any files
# so we have nothing to package !
# Doing a find over the dir adds some overhead, but I can't think of a better way
# of doing it.  I thought about seeing if installwatch.log has greater than one line
# (by default it will always have /dev/tty), but I think that would be unreliable.
#
# Howcome we don't bomb out if the script resulted in error? Well, I don't know
# what you're going to be feeding slacktrack -- for all I know, an exit status of
# 100 could mean it's compiled 'foo' but failed to compile 'bar', but for you, that's
# fine because 'bar' is useless to you.
if [ "$( find ${SLACKTRACKTMPPATH}/TRANSL -print | wc -l )" -le 1 ]; then
   ( printf "slacktrack: installwatch 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"
   ) | tee -a ${SLACKTRACKLOGFILE}
   move_log # we will want to log this error incase we're using slacktrack through an unattended auto builder
   rm -rf ${SLACKTRACKTMPPATH} # tidy up
   exit 5
fi


# Enter the temporary translated path dir that contains our package contents
cd ${SLACKTRACKTMPPATH}/TRANSL


# 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 ) | 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 ) | 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 ./${man_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 ) | 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 object.*not stripped)' | awk -F: '{print $1}' | xargs ${STRIPPROG} --strip-unneeded ) > /dev/null 2>&1
     done
     echo " ... done"
  fi ) | 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} ) > /dev/null 2>&1
     echo " ... done"
  fi ) | 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} --strip-unneeded ) >/dev/null 2>&1
     done
     echo " ... done"
  fi ) | 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} --strip-unneeded ) >/dev/null 2>&1
  # Strip the .a archives
  ( find . -name '*.a' -type f -print0 | xargs -0 ${STRIPPROG} ) > /dev/null 2>&1
  echo " ... done"
  fi ) | 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.  Even though we exclude /usr/tmp in the
# list of dirs passed to 'installwatch', installwatch still creates the symlink
( 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 ) | 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 ) | 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}: Running chown root.bin on binary directories"
     for i in bin/ sbin/ usr/bin/ usr/sbin/; 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 ) | 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}: Running chown root.bin in /bin, /sbin, /usr/bin, /usr/sbin"
     for i in bin/ sbin/ usr/bin/ usr/sbin/; do
         ( cd $i && find . -type f -print0 | xargs -0 chown root.bin ) >/dev/null 2>&1
     done
     echo " ... done"
  fi ) | 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 ) | 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 ) | 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.
# As it happens, we don't neccessarily *need* a build dir because if we 
# specify --nocreatetgz and --nologging then we have no use for it.
# Even if we *are* logging but --nocreatetgz'ing then we may still not need
# one because we may have specified an alternate log file (in a different dir)
# but I'm not going to code to those extremes ;)
if [ "${CREATESLACKWARETGZ}" = "Yes" -o "${LOGGING}" = "Yes" ]; then
   if [ ! -d "${BUILDSTORE}" ]; then
      printf "slacktrack: WARNING: The build store directory ${BUILDSTORE}\n"
      printf "                     does not exist; using /tmp instead\n\n"
      BUILDSTORE="/tmp"
   fi
fi 


# 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.
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


# If we elected not to run the Slackware package maker then don't do anything
# that requires the package to have been built.
# Perhaps we might want to include the logs under this?  Although having a log
# and creating a package are mutually exclusive in my opinion - we should retain
# the logs regardless of whether we create a .tgz.
( if [ "${CREATESLACKWARETGZ}" = "Yes" ]; then
     # Execute the Slackware package making utility & append its output to the package logfile
     ${MAKEPKG} \
       --linkadd $( echo ${CREATESYMLINKS} | cut -b1 | tr A-Z a-z ) \
       --chown   $( echo ${SETROOTOWNER}   | cut -b1 | tr A-Z a-z ) \
       ${BUILDSTORE}/${SLACKWAREPACKAGE} 

     # Install?
     if [ "${INSTALLPACKAGE}" = "Yes" ]; then
        if [ -f "${BUILDSTORE}/${SLACKWAREPACKAGE}" ]; then
           ( cd / ; installpkg ${BUILDSTORE}/${SLACKWAREPACKAGE} )
         else
           echo "${PROGNAME}: wanted to install package but couldn't find it! eek!"
        fi
     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
  
 else
   echo "${PROGNAME}: --nocreatetgz specified; not running 'makepkg'"

 fi ) | 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 ) | 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 ) | tee -a ${SLACKTRACKLOGFILE}


# Tidy up ?
( if [ "${TIDYONFINISH}" = "Yes" ]; then
     echo -n "${PROGNAME}: Deleting installwatch's temporary directory"
      rm -rf "${SLACKTRACKTMPPATH}"
     echo " ... done"
   else
     echo "${PROGNAME}: Temporary workspace '${SLACKTRACKTMPPATH}' will remain"
fi ) | tee -a ${SLACKTRACKLOGFILE}


# Report that slacktrack 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 slacktrack has finished (to screen only).
printf "\n\n[$( date "+%D %r" )] ${PROGNAME} finished.\n" 

exit 0
#EOF
