#!/bin/sh
# Copyright 1994, 1998  Patrick Volkerding, Moorhead, Minnesota USA 
# Copyright 2003  Slackware Linux, Inc.  Concord, CA USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Wed Mar 18 15:32:33 CST 1998
# Patched to avoid possible symlink attacks in /tmp.
#
#
# Sat Dec 09 2000 - Felipe Sanchez <izto@asic-linux.com.mx>
# Removed the code for the questions about symlinks and sane permissions
# They are useless to CheckInstall
#
# Fri Jul 20 2001 - Felipe Sanchez <izto@asic-linux.com.mx>
# Included the patch made to makepkg in the Slackware 8.0 release.
#
# Aug, 2004 = Eko M. Budi
# patch to simplify symlinks creation using readlink (needs coreutil 5.0 up)
# add symlinks to the preexisting doinst.sh (assume it was created by checkinstall) 
#
# Oct, 2004 = Eko M. Budi
# Add dependency tracking for slapt-get
#
# Nov, 2004 = Eko M. Budi, the Dumb Bunny revealed
# Fix tar silly ./ problem
#
# Nov, 2004 = Eko M. Budi & Jason Woodward
# Fix package name function
#
# Nov, 2004 = Eko M. Budi, the Dumber Bunny revealed
# Refix tar silly ./ problem. DOH !!!
# Her ya her ya ... Use the old tar-1.13 !!
#
# Dec, 2004 = Eko M. Budi
# Checkinstall 1.6.0beta4 out, always want to pass options ...
# So combine the original makepkg from Slackware 10
# Renamed to makeslapt, to make it clear
#


TAR=tar-1.13
umask 022
$TAR --help 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
  TAR=tar
fi
if [ ! "`LC_MESSAGES=C $TAR --version`" = "tar (GNU tar) 1.13

Copyright (C) 1988, 92,93,94,95,96,97,98, 1999 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Written by John Gilmore and Jay Fenlason." ]; then
  echo "WARNING: pkgtools are unstable with tar > 1.13."
  echo "         You should provide a \"tar-1.13\" in your \$PATH."
  sleep 5
fi

usage() {
  cat << EOF

Usage: makeslapt package_name.tgz

Makes a Slackware compatible "*.tgz" package containing the contents of the 
current and all subdirectories. If symbolic links exist, they will be removed
and an installation script will be made to recreate them later. This script
will be called "install/doinst.sh". You may add any of your own ash-compatible
shell scripts to this file and rebuild the package if you wish.

options:  
  -s, --slapt y|n   add slapt-get dependency info, default Y
  -l, --linkadd y|n moves symlinks into doinst.sh, default Y.
  -p, --prepend     add symlinks to the front of the existing doinst.sh.
  -c, --chown y|n   resets all permissions to root:root 755, default N

EOF
}


# Return package name, from Jason
# This is fast, but DOES NOT WORK if the package does not follow
# standard package naming, notably VERSION with -, e.g:
# xine-lib-1-rc1-i486-1 --> return xine-lib-1
# In that case, replace '-' with '_'. 
pkgname() {
    echo $1 | sed -re "s/(.*{1,})\\-(.*[\\.\\-].*[\\.\\-].*)[ ]{0,}$/\1/"
}

# return package name, orthodox way
# Not used anymore because the reg-exp way is faster
# although this Orthodox way can handle nasty name better

# put bad guy names here
KNOWN_NAMES="cdparanoia slib libjpeg"
KNOWN_ARCHS="noarch i386 i486 i586 i686 i786 i886 i986"
pkgname1() {
name=${1%%-*}
ver_rest=${1#$name-}
while [ 0 ]; do
   ## 1st rule, if known name then that's it !
   if echo "$KNOWN_NAMES " | grep -q "$name "; then
       break
   fi
   ## 2nd rule, if digits followed by . or - then stop
   if echo $ver_rest | grep -qe "^[0-9]*[\.\-_]"; then
      break
   fi
   ## 3rd, if the next segment is known architecture, stop
   extra=${ver_rest%%-*}
   ver_rest=${ver_rest#$extra-}
   if echo "$KNOWN_ARCHS " | grep -q `echo $ver_rest | cut -f1 -d-`; then
      break
   fi
   ## 4rd, no more rest, then break
   if [ "$ver_rest" = "$extra" ]; then
      break
   fi
   ## concat the name then continue
   name="${name}-${extra}"
done
echo $name
}

## Insert dependency info ala slapt-get 
## The autodependency is generated using ldd ala swaret
## Let them fight as they like, we are free to get the best of them :)

REQUIRED=install/slack-required
DESCRIPTION=install/slack-desc

## Add dependency info if not exist yet
add_required()
{
    if ! grep -qw "$1" $REQUIRED 2>/dev/null; then
    	echo "$*" >> $REQUIRED
    	echo "$*"
    fi
}

## find dependency 
find_required()
{
    ## if $2 not null, assume it is a complete requirement
    if [ "$2" ]; then
	add_required $*
	return 0
    fi
    ## try to find version info from installed packages
    DDNAME=$1
    if ls /var/log/packages/$DDNAME-* &>/dev/null; then
	for DD in /var/log/packages/$DDNAME-* ; do
	    DDBASE=`basename $DD`
	    if [ "$DDNAME" = "`pkgname $DDBASE`" ]; then
		DDVERSION=${DDBASE#${DDNAME}-}
		# Left only version
		DDVERSION=${DDVERSION%%-*}
		add_required $DDNAME '>=' $DDVERSION
		return 0
	    fi
	done
    fi
    ## Can't find version info, just add it then
    add_required $DDNAME 
}

function add_dependency()
{
  # find the executables and track the required packages
  find . -perm +1 ! -path './install/*' -print | while read LINE; do
     [ ! -f "$LINE" ] && continue
     [ ".${LINE##*.}" = ".la" ] && continue
     echo "$LINE:"
     if ! ldd "$LINE" &>/dev/null; then
        # not a dynamic, possibly script
	FTYPE=`file "$LINE"`
	if echo $FTYPE | grep -q "Bourne" ; then
	    find_required bash
	elif echo $FTYPE | grep -q "C shell" ; then
	    find_required tcsh
	elif echo $FTYPE | grep -iqw "perl" ; then
	    find_required perl
	elif echo $FTYPE | grep -iqw "python" ; then
	    find_required python
	elif echo $FTYPE | grep -iqw "ruby" ; then
	    find_required ruby
	elif echo $FTYPE | grep -iqw "php" ; then
	    find_required php
	elif echo $FTYPE | grep -qw "tcl"; then
	    find_required tcl
	elif echo $FTYPE | grep -qw "expect"; then
	    find_required expect
	    find_required tclx
	    find_required tcl
	else
	    echo "WARNING: unknown dependency for $LINE" 
	fi
     else 
	ldd $LINE | while read LINE1; do
    	    LIB=`echo $LINE1 | cut -f1 -d ' '`
	    SELF=$(find -name `basename $LIB`)
	    [ "$SELF" ] && continue
	    grep $LIB /var/log/packages/* | while read LINE2; do
		DFULL=`echo $LINE2 | cut -f1 -d:`
		DBASE=`basename $DFULL`
		DNAME=`pkgname $DBASE`
		case "$DNAME" in
		    aaa_elflibs|$PNAME)
		    continue
		    ;;
		esac
		DVERSION=${DBASE#${DNAME}-}
		DVERSION=${DVERSION%%-*}
		add_required $DNAME '>=' $DVERSION
	    done
	    if [ $? != 0 ]; then
		echo "WARNING : Cannot find dependency for $LIB"
	    fi
	done
     fi
  done
}

function add_doinst() {
    echo "Moving symbolic links to scripts ..."
    # Using readlink to read the link, works with coreutils (Slackware 9.1 up).
    # Old method using ls -l was broken since coreutil 5.0
    find . -type l -print | while read LINE; do
      DIRNAME="`dirname $LINE`" 
      LINKNAME="`basename $LINE`"
      LINKTO="`readlink $LINE`"
      echo "( cd $DIRNAME ; rm -rf $LINKNAME )" >> install/doinst.sh
      echo "( cd $DIRNAME ; ln -sf $LINKTO $LINKNAME )" >> install/doinst.sh
      rm -fv $LINE
    done
}

# Default options
LINKADD=y
PREPEND=y
CHOWN=n
SLAPT=y

# Parse options
while [ 0 ]; do
  if [ "$1" = "--linkadd" -o "$1" = "-l" ]; then
    if [ "$2" = "y" ]; then
      LINKADD=y
    elif [ "$2" = "n" ]; then
      LINKADD=n
    else
      usage
      exit 2
    fi
    shift 2
  elif [ "$1" = "--chown" -o "$1" = "-c" ]; then
    if [ "$2" = "y" ]; then
      CHOWN=y
    elif [ "$2" = "n" ]; then
      CHOWN=n
    else
      usage
      exit 2
    fi
    shift 2
  elif [ "$1" = "--slapt" -o "$1" = "-s" ]; then
    if [ "$2" = "y" ]; then
      SLAPT=y
    elif [ "$2" = "n" ]; then
      SLAPT=n
    else
      usage
      exit 2
    fi
    shift 2
  elif [ "$1" = "-p" -o "$1" = "--prepend" ]; then
    PREPEND=y
    shift 1
  elif [ "$1" = "-h" -o "$1" = "-H" -o "$1" = "--help" -o $# = 0 ]; then
    usage
    exit 0
  else
    break
  fi
done

echo
echo "Slackware SLAPT-GET package maker, version 2.1."
PACKAGE_NAME=$1

PLONG=`basename $PACKAGE_NAME`
PSHORT=`basename $PACKAGE_NAME .tgz`
PNAME=`pkgname $PLONG`

mkdir -p install

if [ "$LINKADD" = "y" ]; then
    if [ "$PREPEND" = "y" ]; then
	echo "Prepending doins script ..."
	touch install/doinst.sh
	mv install/doinst.sh install/doinst.sh.shipped
	echo "#!/bin/sh" > install/doinst.sh
	add_doinst
	echo "" >> install/doinst.sh
	cat install/doinst.sh.shipped >> install/doinst.sh
	rm -f install/doinst.sh.shipped
    else
	echo "Concatenating doinst script ..."
	echo "" >> install/doinst.sh
	add_doinst 
    fi
fi

if [ "$CHOWN" = "y" ]; then
  echo "Fixing permission ..."
  find . -type d -exec chmod -v 755 {} \; 
  find . -type d -exec chown -v root.root {} \;
fi

## Add dependency
if [ "$SLAPT" = "y" ]; then
    echo "Adding slapt-get dependencies ..."
    add_dependency
fi

## Add description, if not yet
if [ ! -f install/slack-desc ]; then
    echo "$PNAME: $PNAME" > install/slack-desc
fi

echo
echo "Creating package $PACKAGE_NAME ..."

# Don't be a dumb bunny, TAR must be tar-1.13
# With newer tar, these are broken:
# tar czvf $PACKAGE_NAME . --> creates leading ./, though fixable by installpkg
# tar czvf $PACKAGE_NAME * --> no leading ./, but installpkg will be confused

echo
echo "Creating tar file $PSHORT.tar..."
echo
$TAR cvf $PSHORT.tar .

# Warn of zero-length files:
find . -type f -size 0c | while read file ; do
  echo "WARNING: zero length file $file"
done
find . -type f -name '*.gz' -size 20c | while read file ; do
  echo "WARNING: possible empty gzipped file $file"
done
echo
echo "Gzipping $PSHORT.tar..."
gzip -9 $PSHORT.tar
echo
echo "Moving $PSHORT.tar.gz to $PACKAGE_NAME..."
mv $PSHORT.tar.gz $PACKAGE_NAME

echo
echo "Package creation complete."
echo
