#!/bin/sh
# pkg
# Vector Linux Packages utility
# Copyright : Vector Linux
# License   : GNU GPL 
# Creator   : Robert S. Lange & Eko M. Budi
# Credit    : The Slackware package tools by P. Volkerdi & Co. 
#             (installpkg, removepkg, etc ...)
#             Checkinstall by F. Duran
# 20041105 : Kocil
# - big overhaul : use slapt-get for deleting packages
#
# 20040919 : Kocil
# - add feature: understand environment ROOT=[directory]
#                affect -i, -u, -o
#
# Changes
# 20040918 : Kocil
# Got to add dependency for the new package system, so:
# - add feature: -i add dependency to log/packages record
# - add feature: -u upgrade (upgradepkg --install-new)
# - add feature: -o overwrite (upgradepkg --reinstall --install-new)
# - add feature: -n record package
# - add feature: -m checkinstall
# - add feature: -x explodepkg
#
# 20040801 : Kocil
# - add feature: -f find a file
# - add feature: -l can list a specific package
# - fix expr syntax error
# - Tidy up the code 
#

if [ ! "$UID" = "0" ]; then
    echo
    echo "[$LOGNAME] You need to run this script as root."
    echo "Try one of these to run it as root: "
    echo "  sudo pkg -i package.tgz"
    echo "  su -c pkg -i package.tgz"
    echo
    exit 
fi

usage() {
cat<<EOF
pkg : Vector Linux package utility
Install/Remove:
    pkg -i <package>     :Install a tgz package
    pkg -u <package>     :Upgrade with newer package or install new
    pkg -o <package>     :Overwrite package or install new
    pkg -r <package>     :Remove package 
Query:
    pkg -l [package]     :List packages in /var/log/packages
    pkg -q <package>     :Find the exact package
    pkg -f[s] <file>     :Find file in any package [summary]
Make/convert:
    pkg -x <package>     :Explode a package to current directory
    pkg -z [package]     :Make a package from current directory
    pkg -n               :Monitor 'make install' to create log record
    pkg -m               :Monitor 'make install' to create a package

options -n or -m, is very recommended for source code installation, e.g:
       ./configure ; make ; pkg -n
Tips, Midnight commander provides the menu for these (press F2)'
EOF

exit
}

## Settings
PKGFORMAT=tgz

## Safely make tmp directory
TMP=/var/tmp/pkg
if [ ! -d $TMP ]; then
  rm -rf $TMP 
  mkdir -p $TMP
  chmod 700 $TMP 
fi

## Set clean exit
trap "rm -rf $TMP" EXIT

##-----------------------------------------------------------
## Query tools

##-----------------------------------------------------------
## List package at /var/log/packages
list_pkg()
{
    if [ ! -d /var/log/packages ]; then
	echo "Strange, no /var/log/packages directory !" 1>&2
	echo "Are you using the right distro ?" 1>&2
	exit 1
    fi
    
    if [ "$1" ]; then
	ls -A -C /var/log/packages/* | grep $1 | while read LINE; do
	    basename $LINE
	done
	exit
    fi

    if [ ! `ls -a /var/log/packages | wc -l` -eq 2 ]; then
	if [ `ls -A /var/log/packages/* | wc -l` -gt 100 ]; then
	    if type -all less >/dev/null 2>&1 ; then
		pager="less"
	    elif type -all more >/dev/null 2>&1 ; then
		pager=more
	    else
		echo "Can't find pager (less or more)."
		ls -A -C /var/log/packages
		exit
	    fi
	    echo "Going to list packages page by page, press q to Quit!"
	    echo -n "Press enter to continue. "
	    read PAUSE
	    ls -A -C /var/log/packages | $pager
	    exit
	else
	    ls -A -C /var/log/packages 
	    exit
	fi
    fi
}

##----------------------------------------------------
## Find the exact pkgname
query_pkg()
{
    for PNAME in $*; do
	for DD in /var/log/packages/$DDNAME-*; do
	    DDBASE=`basename $PP`
	    if [ "$PNAME" = "`pkgname $DDBASE`" ]; then
		echo $DDBASE
		return 0
	    fi
	done
    done
    return 1
}

##---------------------------------------------------
## Find packages that contains a file
## Grep is our friend
find_pkg2()
{
    grep -l -e "/$1" /var/log/packages/* 
}

find_pkg()
{
    grep -l -e "$1" /var/log/packages/* | while read LINE; do
	echo "`basename $LINE` :"
	grep -h -e "$1" $LINE | while read LINE1; do
	    [ -f "/$LINE1" ] && echo "    $LINE1"
	done
    done
}


##---------------------------------------------------
## Create a packagename from current directory
pdirname()
{
    CWD=`pwd`
    PNAMEVER=`basename $CWD`
    # detect architecture
    MARCH=""
    if [ "$CFLAGS" ]; then
	MARCH=`echo ${CFLAGS##*march=} | cut -f1 -d ' '`
    fi
    if [ -z "$MARCH" ]; then
	MARCH=`uname -m`
    fi
    echo $PNAMEVER-$MARCH-1.$PKGFORMAT
}

##-----------------------------------------------------------------
## Monitor "make install" command and create record of install.
## TODO : Should add dependency record !
monitor_error() {
echo "
While running the command: 
$COMMAND 
I got this ERROR!:

`cat $TMP/error`
"
    unset INSTALLWATCHFILE
    unset LD_PRELOAD
    rm -f $TMP/$package*
    exit
}

monitor_pkg() {

if [ "$1" ]; then
    package=$1
else
    package=`pdirname`
fi
PNAME=`pkgname $package`
if query_pkg $PNAME; then
    echo "Package '$PNAME' has been installed."
    echo "Consider to remove it first"
    exit
fi
package=${package%.tgz}
logdir="/var/log/packages"
scriptdir="/var/log/scripts"
mkdir -p $scriptdir

echo
echo "Please enter the command you want to run:"
echo "The default is 'make install' just press enter for it."
echo -n "Command: "
read COMMAND

if [ "$COMMAND" = "" ]; then
    COMMAND="make install"
fi 

echo
echo "Running command '$COMMAND'."
sleep 2

IEXCLUDE="`pwd`,/dev,/proc,/tmp,/var/tmp"

export INSTALLWATCHFILE="$TMP/$package"
cat /dev/null > $INSTALLWATCHFILE
#export LD_PRELOAD="/usr/lib/installwatch.so"
# $COMMAND 2>$TMP/error || monitor_error 

installwatch --logfile=$INSTALLWATCHFILE --exclude="${IEXCLUDE}" \
   --root=${TMP} $COMMAND &> $TMP/error || monitor_error

unset INSTALLWATCHFILE
unset LD_PRELOAD

echo "PACKAGE NAME: $package" > $logdir/$package 
echo "INSTALL COMMAND: $COMMAND" >> $logdir/$package 
echo "DATE: `date`" >> $logdir/$package 
echo "FILE LIST:" >> $logdir/$package 
echo "./" >> $logdir/$package 

rm -f $TMP/$package.a
if [ -x "`type -path gawk`" ]; then
grep -v -E "/dev/|$PWD|/tmp/" $TMP/$package | gawk '{print $3}' | sort -u > $TMP/$package.a
if gawk '{print $2}' $TMP/$package | grep -q "symlink" ; then
grep "symlink" $TMP/$package | gawk '{print $4}' | sort -u > $TMP/$package.s
rm -f $TMP/$package.script 
cat $TMP/$package.s | while read file; do
echo "( cd `dirname $file` ; rm -rf `basename $file` )" >> $TMP/$package.script
echo "( cd `dirname $file` ; ln -sf `ls -l $file | gawk '{print $11}'` `basename $file` )" >> $TMP/$package.script
done 
fi
else
grep -v -E "/dev/|$PWD|/tmp/" $TMP/$package | cut -f3 | sort -u > $TMP/$package.a
if cut -f2 $TMP/$package | grep -q "symlink" ; then
grep "symlink" $TMP/$package | cut -f4 | sort -u > $TMP/$package.s
rm -f $TMP/$package.script 
cat $TMP/$package.s | while read file; do
echo "( cd `dirname $file` ; rm -rf `basename $file` )" >> $TMP/$package.script
echo "( cd `dirname $file` ; ln -sf `ls -l $file | cut -d' ' -f29` `basename $file` )" >> $TMP/$package.script
done 
fi
fi

rm -f $TMP/$package.b 
cat $TMP/$package.a | while read file; do
if [ -e "$file" ]; then
    echo $file >> $TMP/$package.b
fi
done 

cat $TMP/$package.b | sed "s/^\///g" >> $logdir/$package 
    
if [ -s $TMP/$package.script ]; then 
    mv $TMP/$package.script /var/log/scripts/$package
    chmod 755 /var/log/scripts/$package 2>/dev/null
fi

rm -f $TMP/$package*

echo
echo "Package Log: /var/log/packages/$package"
echo "Done..."
echo "You can remove this package later by command"
echo "  removepkg `pkgname $package`"
exit
}
# End of monitor.

##--------------------------------------------------------------------
## Create a package from make install
## Use checkinstall man :)
create_pkg()
{
   if which checkinstall &>dev/null; then
	checkinstall "$@"
    else
	echo "ERROR: Cannot find checkinstall"
    fi    
}

##--------------------------------------------------------------------
## Explode package to a directory
explode_pkg()
{
PKG=$1
echo "Exploding package $PKG in current directory:"
( umask 000 ; $TAR xzvf $PKG 2> /dev/null )
cat<<EOF
Package $1 has been exploded.
After examining it, you may repackaged it by using
   pkg -z [new_package_name]

EOF
}

##----------------------------------------------------------
## Make a package and txt description
## From the current directory
make_pkg_txt()
{
    if [ "$1" ]; then
	PFULL=$1
    else
	PFULL="../`pdirname`"
    fi
    PDIRSHORT=${PFULL%.*}
    makepak $PDIRSHORT.$PKGFORMAT
}

##--------------------------------------------------------------------
## Remove packages
## Uses slapt-get now, if exist, to handle dependencies
remove_pkg() {
    if which slapt-get &> /dev/null; then
	slapt-get --remove $1
    else
	removepkg $1
    fi
}

##------------------------------------------------------------------
## install package 
install_pkg()
{
  installpkg $1
}

##------------------------------------------------------------------
## upgrade pkg no matter what, even if newer
## Use slackware tool, since installpkg has been hacked
overwrite_pkg() {
   upgradepkg --install-new --reinstall $1
}

##------------------------------------------------------------------
## upgrade pkg if newer 
upgrade_pkg() {
  upgradepkg --install-new $1
}

##------------------------------------------------------------------
## convert_pkg
## I don't think this is going to work.
## where is the unrpm, undep, unslp ??
convert_pkg() {
    PFULL=$1
    PLONG=`basename $PFULL`
    FROM_TYPE=${PLONG##*.}
    SHORTNAME=${PLONG%.*}
    
    if [ "$PKGFORMAT" = "tbz" ] && [ "$FROM_TYPE" = "tgz" ]; then
	# piece of cake
	cp $PFULL $SHORTNAME.tar.gz
	gunzip $SHORTNAME.tar.gz
	bzip2 $SHORTNAME.tar
	mv $SHORTNAME.tar.bz2 $SHORTNAME.tbz
	exit 
    fi
    
    if [ "$MKPKG_TYPE" = "tgz" ] && [ "$FROM_TYPE" = "tbz" ]; then
	# piece of cake too
	cp $PFULL $SHORTNAME.tar.bz2
	bunzip2 $SHORTNAME.tar.bz2
	gzip -9 $SHORTNAME.tar
	mv $SHORTNAME.tar.gz $SHORTNAME.tgz
	exit 
    fi

    if echo $PFULL | grep -v -E "\.src.rpm$" | grep -E -q "\.rpm$" ; then
    if [ ! -x "`type -path unrpm`" ]; then
    echo
    echo "Can't find 'unrpm' to check rpm package!"
    exit
    fi
    echo
    echo "Checking rpm package for errors '$PFULL'..."
    unrpm < $PFULL | gzip -d | cpio -i --only-verify-crc 2>/tmp/rpm.error 
    if [ $? -gt 0 ]; then
    echo
    echo "ERROR! reported for '$PFULL'..." 
    echo "There's something wrong with the package, you probably shouldn't convert it." 
    echo
    rm -f /tmp/rpm.error
    exit 
    elif `grep -q "checksum error" /tmp/rpm.error` ; then
    echo
    echo "ERROR! reported for '$PFULL'..." 
    echo "There's something wrong with the package, you probably shouldn't convert it." 
    echo
    rm -f /tmp/rpm.error
    exit 
    fi
    rm -f /tmp/rpm.error
    D="`basename $PFULL .rpm`"
    echo
    echo "Converting '$PFULL' to '`basename $PFULL .rpm`.tgz'..."
    echo
    dir=$PWD
    mkdir -p /tmp/$D 
    cd /tmp/$D || exit 
    unrpm < $dir/$PFULL | gzip -d | cpio -iumd --quiet 
    find . -type d -perm 700 -exec chmod 755 {} \; 2>/dev/null
    mkpkg $D 
    if [ $? -gt 0 ]; then
    cd $dir && rm -rf /tmp/$D
    exit 
    else
    mv $D.tgz $dir && cd $dir && rm -rf /tmp/$D
    exit
    fi
    elif echo $PFULL | grep -E -q "\.deb$" ; then
    if [ ! -x "`type -path undeb`" ]; then
    echo
    echo "Can't find 'undeb' to check deb package!"
    exit
    fi
    echo
    echo "Checking deb package for errors '$PFULL'..."
    undeb -p $PFULL data.tar.gz | tar -tz >/dev/null 2>&1
    if [ $? -gt 0 ]; then
    echo
    echo "ERROR! reported for '$PFULL'..." 
    echo "There's something wrong with the package, you probably shouldn't convert it." 
    echo
    exit 
    fi
    D="`basename $PFULL .deb`"
    echo
    echo "Converting '$PFULL' to '`basename $PFULL .deb`.tgz'..."
    echo
    dir=$PWD
    mkdir -p /tmp/$D && undeb -p $PFULL data.tar.gz | tar -xzpf - -C /tmp/$D && cd /tmp/$D && mkpkg $D 
    if [ $? -gt 0 ]; then
    cd $dir && rm -rf /tmp/$D
    exit 
    else
    mv $D.tgz $dir && cd $dir && rm -rf /tmp/$D
    exit
    fi
    elif echo $PFULL | grep -E -q "\.slp$" ; then
    D="`basename $PFULL .slp`"
    echo
    echo "Converting '$PFULL' to '`basename $PFULL .slp`.tgz' ..."
    echo
    dir=$PWD
    mkdir -p /tmp/$D && tar -xpf $PFULL -C /tmp/$D --use-compress-program bzip2 2>/dev/null
    cd /tmp/$D && mkpkg $D 
    if [ $? -gt 0 ]; then
    cd $dir && rm -rf /tmp/$D
    exit 
    else
    mv $D.tgz $dir && cd $dir && rm -rf /tmp/$D
    exit
    fi
    else
    echo
    echo "$PFULL" 
    echo "Doesn't have a .tgz .rpm, .deb, or .slp extension."
    echo
    exit
    fi
}

case $1 in
    --sourced)
        ;;
    -l) list_pkg $2
	;;
    -q) if [ "$2" ]; then
	    shift
	    query_pkg $*
	else
	    usage
	fi
	;;
    -f) 
	if [ "$2" ]; then
	    find_pkg $2
	else
	    usage
	fi
	;;
    -fs) 
	if [ "$2" ]; then
	    find_pkg2 $2
	else
	    usage
	fi
	;;
    -c) 
	if [ "$2" ]; then
	    PKGFORMAT="tgz"
	    convert_pkg $2
	else
	    usage
	fi
	;;
    -b)
	if [ "$2" ]; then
	    PKGFORMAT="tbz"
	    convert_pkg $2
	else
	    usage
	fi
	;;
    -x)
	if [ "$2" ]; then
	    explode_pkg $2
	else
	    usage
	fi
	;;
    -z) make_pkg_txt $2
	;;
    -n) monitor_pkg $2
	;;
    -m) create_pkg $2 $3 $4
	;;
    -r) 
	if [ "$2" ]; then
	    remove_pkg $2
	else
	    usage
	fi;;
    -i)
	if [ "$2" ]; then
	    install_pkg $2
	else
	    usage
	fi
	;;
    -o)
	if [ "$2" ]; then
	    overwrite_pkg $2
	else
	    usage
	fi
	;;
    -u)
	if [ "$2" ]; then
	    upgrade_pkg $2
	else
	    usage
	fi
	;;
    *)
	usage
	;;
esac

