#!/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
#
VERSION=1.2.2
SLACKWARE_VERSION=`cat /etc/slackware-version | cut -f2 -d\ `
SLACKKEY="Slackware Linux Project <security@slackware.com>"
CONF=/etc/slackpkg
SOURCE=`grep -e "^\([a-z]\)" $CONF/mirrors`
. $CONF/slackpkg.conf
LOCAL=0

#
# Load the slackpkg functions
#
. /usr/libexec/slackpkg/core-functions.sh

#
# Load *extra* functions and modules to slackpkg
#
# if you want a new function or need a rewrite of one existing
# feature, you can put your new function in a shell script, under
# /usr/libexec/slackpkg/functions.d
#
# Remember, the new function scripts needs to be executable
#
for i in /usr/libexec/slackpkg/functions.d/*; do
	if [ -x $i ]; then
		. $i
	fi
done

#========================================================================
#
# 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 is the first time running slackpkg
#
if ! [ -f ${CONF}/pkglist ] && [ "$1" != "update" ]; then
	echo -e "\
\nHey! Probably this is the first time you are running slackpkg.\n\
Before install|upgrade|reinstall anything, you need to uncomment\n\
one mirror in ${CONF}/mirrors and run:\n\n\
\t# slackpkg update\n\n\
You can see more information about slackpkg functions in slackpkg manpage."
	cleanup
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" ] && [ "$1" != "info" ]; 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

# Check if gpg is enabled but no GPG command are found.
#
if ! [ "$(which gpg 2>/dev/null)" ] && [ "${NOGPG}" = "0" ]; then
	NOGPG=1
	echo -e "\n\
No gpg found!!! Please, disable GPG in /etc/slackpkg/slackpkg.conf or install\n\
the gnupg package.\n\n\
To disable GPG, edit slackpkg.conf and add one line with NOGPG=1.\n\
You can see an example in slackpkg.conf.new.\n "
	sleep 5
fi 

# Check if the Slackware GPG key are found in the system
#
GPGFIRSTTIME="`gpg --list-keys \"$SLACKKEY\" 2>/dev/null \
		| grep -c \"$SLACKKEY\"`"
if [ "$GPGFIRSTTIME" = "0" ] && [ "$1" != "search" ] && [ "$1" != "info" ] && \
		[ "$1" != "update" ] && [ "$NOGPG" != "1" ]; then
	echo -e "\n\
You need the GPG key of $SLACKKEY.\n\
To download and install that key, run:\n\n\
\t# slackpkg update gpg\n\n\
You can disable GPG checking, too. But it isn't a good idea.\n\
To disable GPG, edit slackpkg.conf and add one line with NOGPG=1.\n\
You can see an example in slackpkg.conf.new.\n"
	cleanup
fi
echo

#========================================================================
#
# MAIN PROGRAM
#

#
# Sanitize $2. We have some problems with dots and plus (.+)
#
ARG2="`echo $2 | sed -e 's/\+/\\\+/g' -e 's/\./\\\./g'`"

#
# Clean /tmp files (maybe /tmp have this "trash") 
#
rm -f /tmp/FILELIST.TXT /tmp/*MANIFEST* /tmp/*PACKAGES.TXT \
	/tmp/tmplist /tmp/blacklist.* /var/run/slackpkg.$$ &>/dev/null

#
# A *BIG* case with all slackpkg commands -:)
#
case "$1" in
	"update")
		# If you are using "slackpkg update gpg" OR the system
		# doesn't have Slackware GPG key, download and install
		# the key
		#
		if [ "$ARG2" = "gpg" ] || [ "$GPGFIRSTTIME" = "0" ]; then
			getfile /GPG-KEY /tmp/gpgkey
			gpg --yes --batch --delete-key "$SLACKKEY" &>/dev/null
			gpg --import /tmp/gpgkey &>/dev/null && \
			echo -e "\t\t\tSlackware Linux Project's GPG key added"
			rm /tmp/gpgkey
			if [ "$ARG2" ]; then
				cleanup
			fi
		fi
		echo "Updating the package lists..."
		echo -e "\tDownloading..."
		#
		# Download MANIFEST, FILELIST.TXT and CHECKSUMS.md5
		#

		# That will be download MANIFEST.bz2 files in /slackware
		# /extra and /pasture. 
		#
		echo -e "\t\tList of all files"
		for i in patches slackware extra pasture; do
			getfile ${i}/MANIFEST.bz2 /tmp/${i}-MANIFEST.bz2 && \
				DIRS="$DIRS $i"
		done

		echo -e "\t\tPackage List"
		getfile FILELIST.TXT /tmp/FILELIST.TXT

		if [ "$CHECKPKG" = "1" ]; then
			echo -e "\t\tChecksums"
			getfile CHECKSUMS.md5 ${CONF}/CHECKSUMS.md5
		fi
		
		# Download all PACKAGES.TXT files
		# 
		echo -e "\t\tPackage descriptions"
		for i in $DIRS; do
			getfile ${i}/PACKAGES.TXT /tmp/${i}-PACKAGES.TXT
		done

		# Format FILELIST.TXT
		#
		echo -e "\tFormating lists to slackpkg style..."
		echo -e "\t\tPackage List"
		awk '/tgz/ && !/source\// && !/testing\// && !/.asc/ {print $NF}' /tmp/FILELIST.TXT | tr -d "\r" > $CONF/pkglist
		
		# Format MANIFEST
		#
		
		# bunzip and concatenate all MANIFEST files
		#
		echo -e "\t\tList of all files"
		for i in $DIRS; do
			bunzip2 /tmp/${i}-MANIFEST.bz2
			cat /tmp/${i}-MANIFEST >> /tmp/MANIFEST
		done
		
		awk -f $CONF/filelist.awk /tmp/MANIFEST > $CONF/filelist
		gzip -f $CONF/filelist

		# Concatenate PACKAGE.TXT files
		#
		echo -e "\t\tPackage descriptions"
		for i in $DIRS; do
			cat /tmp/${i}-PACKAGES.TXT >> /tmp/PACKAGES.TXT
		done
		cp /tmp/PACKAGES.TXT $CONF/PACKAGES.TXT
	;;
	"install")
		makelist $ARG2
		if [ -n "$INSTALLPKG" ]; then
			showlist "$INSTALLPKG" $1
			for i in $INSTALLPKG; do
				getpkg $i installpkg Installing 
			done
		else
			echo -e "No packages matches the pattern for install. Try:"
			echo -e "\n\t$0 reinstall|upgrade $2\n"
		fi
	;;
	"reinstall")
		makelist $ARG2
		if [ -n "$REINSTALLPKG" ]; then
			REINSTALLPKG=` echo $REINSTALLPKG | tr " " "\n" | \
sort | uniq | tr "\n" " "`
			showlist "$REINSTALLPKG" $1
			for i in $REINSTALLPKG; do
				getpkg $i installpkg Reinstalling
			done
		else
			echo -e "No packages matches the pattern for reinstall. Try:"
			echo -e "\n\t$0 install|upgrade $2\n"
		fi
	;;
	"upgrade")
		makelist $ARG2
		if [ -n "$UPGRADEPKG" ]; then
			showlist "$UPGRADEPKG" $1
			for i in $UPGRADEPKG; do
				getpkg $i upgradepkg Upgrading
			done
		else
			echo -e "No packages matches the pattern for upgrade. Try:"
			echo -e "\n\t$0 install|reinstall $2\n"
		fi
	;;
	"download")
		makelist $ARG2
		DOWNLOADPKG=`\
echo $UPGRADEPKG $INSTALLPKG $REINSTALLPKG | tr " " "\n" | sort | uniq | \
tr "\n" " "`
		DELALL="0"
		if ! [ "$DOWNLOADPKG" = " " ]; then
			showlist "$DOWNLOADPKG" $1
			for i in $DOWNLOADPKG; do
				getpkg $i true 
			done
		else
			echo -e "No packages matches the pattern for download."
		fi
	;;
	"remove")
		FILE=`ls -1 /var/log/packages | \
		 	    sed 's/\+/\\\+/g' | \
			    egrep -i "^${2}-[^-]+-(i[3456]86|noarch)-"`
		if [ "$FILE" = "" ]; then
			echo -e "The file $1 can't be removed, package not installed.\n"
			cleanup
		fi
		showlist "$FILE" $1
		for i in $FILE; do
			echo -e "\nPackage: $i"
			echo -e "\tRemoving... "
			removepkg $i
		done
	;;
	"blacklist")
		BLACKLISTFILE="/tmp/blacklist.$$"
		makelist $ARG2
		for i in $UPGRADEPKG $INSTALLPKG $REINSTALLPKG; do
			BASENAME=`cutpkg $i`
			BLACKLIST="$BLACKLIST $BASENAME"
		done
		BLACKLIST=`echo $BLACKLIST | tr ' ' "\n" | sort | uniq`
		echo $BLACKLIST | tr ' ' "\n" > ${BLACKLISTFILE}
		if [ "$BLACKLIST" = "" ]; then
			echo -e "No packages matches the pattern."
			cleanup
		else
			showlist "$BLACKLIST" $1
		fi
		
		grep "^#" ${CONF}/blacklist > ${BLACKLISTFILE}.new
		grep -v "^#" ${CONF}/blacklist >> ${BLACKLISTFILE} 
		
		cat ${BLACKLISTFILE} | grep -v "^$" | sort | \
			uniq >> ${BLACKLISTFILE}.new
		mv ${BLACKLISTFILE}.new ${CONF}/blacklist 
		
		echo -e "\nPackages added to your blacklist.\n\
If you want to remove those packages, edit ${CONF}/blacklist."
	;;
	"search")
		# Search filelist.gz for possible matches
		PACKAGES=`zegrep $ARG2 $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 below shows all packages with the selected pattern.\n"
		    for i in $PACKAGES; do
			if [ "$BASENAME" = "$(cutpkg ${i})" ]; then
				continue
			fi
			# BASENAME is base package name 
			BASENAME="$(cutpkg ${i})"

			# RAWNAME is Latest available version  
			RAWNAME="$(basename ${i} .tgz)"

			# Default is uninstalled
			STATUS="uninstalled"

			# First is the package already installed?
			# Amazing what a little sleep will do
			# exclusion is so much nicer :)
			INSTPKG=$(ls -1 /var/log/packages | \
				grep -e "^${BASENAME}-[^-]\+-\(i[3456]86\|noarch\)-[[:digit:]]\+")

			    # INSTPKG is local version
			    if [ ! "${INSTPKG}" = "" ]; then

				# If installed is it uptodate?
				if [ "${INSTPKG}" = "${RAWNAME}" ]; then
				    STATUS=" installed "
			    	    echo "[${STATUS}] - ${INSTPKG}"
				else
				    STATUS="  upgrade  "
				echo "[${STATUS}] - ${INSTPKG} --> ${RAWNAME}"
				fi
			    else
				    echo "[${STATUS}] - ${RAWNAME}"
			    fi
		    done
		fi
	;;
	"info")
		NAME=`cutpkg $ARG2`
		awk -F: "/PACKAGE NAME:.* ${NAME}-[^-]+-(i[3456]86|noarch)-[[:digit:]]+/,/^$/ {
                                found=1
				 if (\$1 ~ /"$NAME"/) {
				 print \$ARG2 
				} else {
				print \$0
				} 
                        }
                        END {
				if ( found != 1 ) {
			print \"No packages found! Try:\n\n\tslackpkg search $ARG2\n\nAnd choose one (and only one package).\n\"
				}
			}" /etc/slackpkg/PACKAGES.TXT
	;;
	*)
		usage
	;;
esac

cleanup
