#!/bin/sh
#
# SlackPkg - An Automated packaging tool for Slackware Linux
# Copyright (C) 2003 Roberto F. Batista, Evaldo Gardenali
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Project Page: http://slackpkg.sf.net/
# Roberto F. Batista (aka PiterPunk) piterpk@terra.com.br
# Evaldo Gardenali (aka UdontKnow) evaldogardenali@fasternet.com.br
#

#
# LOAD CONFIGURATIONS
#

#
# CONF = configuration directory
# SOURCE = A mirror of Slackware. Source can be sett by editing $CONF/mirrors
#
CONF=/etc/slackpkg
SOURCE=`grep -e "^\([a-z]\)" $CONF/mirrors`
. $CONF/slackpkg.conf
LOCAL=0

#
# PROGRAM FUNCTIONS
#

# Clean-up tmp and lock files
function cleanup() {
	echo
	if [ "$DELALL" = "1" ] && [ "$NAMEPKG" != "" ]; then
		rm $TEMP/$NAMEPKG &>/dev/null
	fi		
	( rm -f /var/lock/slackpkg.$$ && \
	  rm -f /tmp/FILELIST.TXT /tmp/MANIFEST* ) 2>/dev/null
	exit
}

# Got the name of a package, without version-arch-release data
function cutpkg() {
	echo ${1/.tgz/} | awk -F'-' 'OFS="-" { if (NF - 3 > 0) NF=NF-3 } \
					     { print $0 }'
}

# Show the slackpkg usage
function usage() {
	echo -e "\nUsage: \t$0 update\n\
\t$0 install|reinstall|remove|upgrade packagename\n\
\t$0 search file\n"
	cleanup
}

function checkpkg() {
	MD5ORIGINAL=`grep "${1}$" ${CONF}/CHECKSUMS.md5| cut -f1 -d \ `
	MD5DOWNLOAD=`md5sum ${TEMP}/$NAMEPKG | cut -f1 -d \ `
	if [ "$MD5ORIGINAL" = "$MD5DOWNLOAD" ]; then
		echo 1 
	else
		echo 0 
	fi
}

# Function to download the correct package and many "checks"
#
function getpkg() {
	ISOK="1"
	NAMEPKG=`echo $1 | awk -F '/' '{print $NF}'`
	
	# Check if the mirror are local, if is local, copy files to $TEMP
	# else, download packages from remote host and put then in $TEMP
	#
	if [ "$LOCAL" = "1" ]; then 
		cp ${SOURCE}${1} $TEMP
	else
		echo -e "Downloading the package $NAMEPKG"
		wget $WGETFLAGS -P $TEMP -nd ${SOURCE}${1}
	fi

	# If MD5SUM checks are enabled in slackpkg.conf, check the
	# packages md5sum to detect if they are corrupt or not
	#
	if [ "$CHECKPKG" = "1" ]; then
		echo -e "Checking the package $NAMEPKG"
		ISOK=`checkpkg $1`
	fi
	if [ "$ISOK" = "1" ]; then
		( cd $TEMP && $2 $NAMEPKG )
	else
		echo "Error! $NAMEPKG is corrupted!"
		rm $TEMP/$NAMEPKG
	fi

	# If DELALL is checked, all downloaded files will be erased
	# after installed/upgraded/reinstalled
	#
	if [ "$DELALL" = "1" ]; then
		rm $TEMP/$NAMEPKG
	fi		
}

#
# Trap CTRL+C and kill
#
trap 'cleanup' 2 14 15

#
# SYNTAX CHECKING
#

# Checking if another instance of slackpkg is running

if [ "`ls /var/lock/slackpkg.* 2>/dev/null`" ] && [ "$1" != "search" ]; then
	echo -e "\
\nAnother instance of slackpkg is running. If this isn't true, you can remove\n\
/var/lock/slackpkg.* files and run slackpkg again.\n"
	exit
else
	ls /var/lock/slackpkg.* &>/dev/null || touch /var/lock/slackpkg.$$
fi

# Checking if /etc/slackpkg/mirrors are in correct syntax.

if [ "$SOURCE" = "" ]; then
	echo -e "\
\nYou don't have any mirror selected in /etc/slackpkg/mirrors\n\
Please, edit that file and uncomment one mirror. The Slackpkg\n\
only works with ONE mirror selected.\n"
	cleanup
else
	COUNT=`echo $SOURCE | wc -w | tr -d " "`
	if [ "$COUNT" != "1" ]; then
		echo -e "\n\
Slackpkg only works with ONE mirror selected. Please, edit your\n\
/etc/slackpkg/mirrors and comment one or more lines. Two or more\n\
mirrors uncommented isn't a valid syntax.\n"
		cleanup
	fi
fi

#
# It will check if the mirror selected are ftp.slackware.com
# if are "ftp.slackware.com" tell to the user to choice other
#
if echo ${SOURCE} | grep "^ftp://ftp.slackware.com" &>/dev/null ; then
	echo -e "\n\
Please, use one of the mirrors.\n\
ftp.slackware.com should be preserved so the\n\
mirrors can be kept up-to-date.\n"
	cleanup
fi

# Checking if the user have the permissions to install/upgrade/update
if [ "`id -u`" != "0" ] && [ "$1" != "search" ]; then
	echo -e "\n\
Only root can install, upgrade or remove packages.\n\
Please, log as root or call your system administrator.\n"
	cleanup
fi

# Command line syntax checking 
#
if [ "$#" = "0" ]; then
	usage
fi
if [ "$#" = "1" ] && [ "$1" != "update" ]; then
	usage
fi

# Check if the mirror are local (cdrom or file)
#
MEDIA=`echo ${SOURCE} | cut -f1 -d:`
if [ "$MEDIA" = "cdrom" ] || [ "$MEDIA" = "file" ]; then
	SOURCE=/`echo ${SOURCE} | cut -f3- -d/`
	LOCAL=1
fi

# Check if we have md5sum in the PATH. Without md5sum, disables
# md5sum checks
#
if ! [ `which md5sum 2>/dev/null` ]; then
	CHECKPKG=0
elif ! [ -f ${CONF}/CHECKSUMS.md5 ] && \
	[ "$1" != "update" ] && \
	[ "$CHECKPKG" = "1" ]; then
	echo -e "\n\
No CHECKSUMS.md5 found! Please, disable md5sums checking\n\
on your /etc/slackpkg/slackpkg.conf or run slackpkg update\n\
to download a new CHECKSUMS.md5 file.\n"
	cleanup
fi

echo
#
# Download and convert the FILELIST.TXT and MANIFEST.bz2 to an easier format
#
if [ "$1" = "update" ]; then
	MANIFEST="MANIFEST.bz2"
	
	# Download MANIFEST, FILELIST.TXT and CHECKSUMS.md5
	if [ "$LOCAL" = "1" ]; then
		cp ${SOURCE}slackware/$MANIFEST /tmp/$MANIFEST
		cp ${SOURCE}FILELIST.TXT /tmp/FILELIST.TXT
		if [ "$CHECKPKG" = "1" ]; then
			cp ${SOURCE}CHECKSUMS.md5 ${CONF}/CHECKSUMS.md5
		fi
	else
		wget $WGETFLAGS ${SOURCE}slackware/$MANIFEST -O /tmp/$MANIFEST
		wget $WGETFLAGS ${SOURCE}FILELIST.TXT -O /tmp/FILELIST.TXT
		if [ "$CHECKPKG" = "1" ]; then
			wget $WGETFLAGS ${SOURCE}CHECKSUMS.md5 -O ${CONF}/CHECKSUMS.md5
		fi
	fi

	# Format FILELIST.TXT
	awk '/tgz/ && !/source\// && !/.asc/ {print $9}' /tmp/FILELIST.TXT > $CONF/pkglist
	
	# Format MANIFEST
	bunzip2 /tmp/$MANIFEST
	awk -f $CONF/filelist.awk /tmp/MANIFEST > $CONF/filelist
	gzip -f $CONF/filelist
fi

#
# Executing "install" and "upgrade" procedures
#
if [ "$1" = "install" ] || [ "$1" = "upgrade" ] || [ "$1" = "reinstall" ]; then
	#
	# Check if the package pattern is found in pkglist
	#
	# The search begins in $FIRST, after $SECOND, after $THIRD and,
	# at last $FOURTH. That schema makes "patches" dir searched before
	# "slackware".
	#
	FILE=""
	CRUDELIST=`grep -i "/$2" $CONF/pkglist | awk -F/ '{ print $NF}'| \
		awk -F- 'OFS="-" { NF=NF-3 } { print $0 }' | sort | uniq`
	for i in $CRUDELIST; do
		TEST=`grep -e "$FIRST" $CONF/pkglist | grep "/$i-[0-9]"` ||\
		TEST=`grep -e "$SECOND" $CONF/pkglist | grep "/$i-[0-9]"` ||\
		TEST=`grep -e "$THIRD" $CONF/pkglist | grep "/$i-[0-9]"` ||\
		TEST=`grep -e "$FOURTH" $CONF/pkglist | grep "/$i-[0-9]"`
		
		NAMEPKG=`echo ${TEST/.tgz/} | awk -F '/' '{print $NF}'`
		BLACK=`cutpkg $NAMEPKG`
		grep "^${BLACK}$" $CONF/blacklist &>/dev/null && TEST=""
		
		FILE="$TEST $FILE"
	done
	if [ "$FILE" = "" ]; then
		echo -e "No packages matches the pattern $2\n"
		cleanup
	fi
	#
	# Show only the package names. And make some checking.
	#
	FILEINST=""
	FILEUPG=""
	FINDIT=0
	for i in $FILE; do
		#
		# NAMEPKG = Name of the package
		# FINDPKG = Package already installed
		#
		NAMEPKG=`echo ${i/.tgz/} | awk -F '/' '{print $NF}'`
		FINDPKG=`cutpkg $NAMEPKG`
		FINDPKG=`ls /var/log/packages | grep "^${FINDPKG}-[0-9]"`
		#
		# IF the selected method is "install" and the package
		# aren't installed, make a filelist with those packages
		#
		if [ "$1" = "install" ] && [ "$FINDPKG" = "" ]; then
			FILEINST="$i $FILEINST"
			FINDIT=1
			echo -e "$NAMEPKG" 
		#
		# IF method is "upgrade" and already have a version of
		# the package installed, make a filelist with those
		# packages.
		#
		elif [ "$FINDPKG" != "" ]; then
			ALREADY=`ls /var/log/packages | grep $NAMEPKG`
			if [ "$ALREADY" = "" ] && [ "$1" = "upgrade" ]; then
				FILEUPG="$i $FILEUPG"
				FINDIT=1
				echo -e "$NAMEPKG" 
			elif [ "$ALREADY" != "" ] && [ "$1" = "reinstall" ]; then
				FILEINST="$i $FILEINST"
				FINDIT=1
				echo -e "$NAMEPKG" 
			fi
		fi
	done
	#
	# Verify the lists. If doesn't have a package to install/upgrade,
	# print a message and exit program
	#
	if [ "$FINDIT" = "0" ]; then
		TRY=install
		[ "$1" = "install" ] && TRY=upgrade
		echo -e "No packages matches the pattern for $1. Try:"
		echo -e "\n\t$0 $TRY $2\n"
		cleanup
	fi
	
	#
	# Ask if that packages will be upgraded/installed or not.
	#
	echo -e "\nDo you wish to $1 that packages (Y/n)? \c"; read ANSWER
	if [ "$ANSWER" = "n" ] || [ "$ANSWER" = "N" ]; then
		cleanup
	fi
	
	echo
	#
	# Download/Install/Upgrade each package
	#
	case "$1" in
		"install" | "reinstall")
		for i in $FILEINST; do
			getpkg $i installpkg 
		done
		;;
		"upgrade")
		for i in $FILEUPG; do
			getpkg $i upgradepkg
		done
		;;
	esac
fi

#
#  Remove installed packages
#
if [ "$1" = "remove" ]; then
	FILE=`ls /var/log/packages | grep -i "$2"`
	if [ "$FILE" = "" ]; then
		echo -e "The file $1 can't be removed, package not installed.\n"
		cleanup
	fi
	for i in $FILE; do
		echo $i
	done
	echo -e "\nDo you wish to remove those packages (Y/n)? \c"; read ANSWER
	if [ "$ANSWER" = "n" ] || [ "$ANSWER" = "N" ]; then
		cleanup
	fi
	for i in $FILE; do
		removepkg $i
	done
fi

if [ "$1" = "search" ]; then
	PACKAGES=`zgrep $2 $CONF/filelist.gz | cut -d " " -f 1 | awk -F'/' '{print $NF}'`
	if [ "$PACKAGES" = "" ]; then
		echo "No package contains the selected pattern."
	else
		echo -e "The list above shows all packages with the selected pattern.\n"
		for i in $PACKAGES; do
			STATUS=uninstalled
			NAME=`cutpkg $i`
			NAME=`ls /var/log/packages | grep "^${NAME}-[0-9]"`
			IFPK=`grep $2 /var/log/packages/$NAME 2>/dev/null`
			if [ "$IFPK" = "" ]; then
				NAME=`echo ${i/.tgz/}`
			else
				STATUS=" installed "
			fi
			echo "[${STATUS}] - $NAME"
		done
	fi
fi

cleanup
