#!/bin/bash
#
# File: /usr/local/bin/inkapkginform
#
#  give information about installed/available tarball-packages
#
#    Copyright (C) 2013  Ingo Kaesmann
#
#    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
#
#
# Script template: 0.3.0
#
# Exit codes:
# 0 = OK
# 1 = Error in parameters
# 2 = Error in configfile, configfile old or not found
# 3 = Library old or not found
# 8 = Error in other file or other file not found
# 15= Not from all server info-list available
##############################################################################
# SOURCE FILES

. /usr/local/etc/main-inka-sh.conf			# config main
. /usr/local/etc/inka-basis.conf			# global config
. $LLIBDIR/lib-inka-std.sh				# functions standard
. $LLIBDIR/lib-inka-basis.sh				# functions basis
##############################################################################
# DECLARATION OF VARIABLES

# STRINGS
pkgname=inka-basis					# package name
lib_inka_std_sh_needed=1.3.6				# standard lib version
lib_inka_basis_sh_needed=1.3.3				# basis lib version
conf_file_needed=1.3.0					# conf file version
#----------------------- end of variables to configure -----------------------
version=$(grep "^VERSION" $PROGREG/$pkgname.inf | cut -f 2)	# version
scriptname=$(basename $0)				# name of script
tempfile=$TEMPDIR/$scriptname.$UID.$$.tmp		# temporary file
infolog="logger -p user.info -t $scriptname --"		# log info messages
errlog="logger -p user.err -t $scriptname -- ERROR:"	# log error messages
debuglog="logger -p user.debug -t $scriptname -- DEBUG:" # log debug messages
debug=no						# debug=yes/no
verbose=""						# verbose=""/-q/-v
opt_found=no						# opt_found=yes/no
opt=""							# option
#------------------------- end of standard variables -------------------------
llist=${tempfile}.1.tmp				# local list of packages
rlist=${tempfile}.2.tmp				# remote list of packages
# NUMBERS
err=0							# exit code
##############################################################################
# FUNCTIONS

function show_help ()
{
# Show help
# Uses: cat
# Return codes: standard

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_help: $# $@" >&2
	#$debuglog show_help: $# $@
fi

cat <<EOT

Aufruf: $scriptname -a|-i|-A|-N|-S|-h|--version|--show-config [-q|-v] [--debug]
        $scriptname -c|-f PAKET | -p DATEI | -I URL [-q|-v] [--debug]
Gibt Informationen ueber installierte/installierbare Pakete

        -a      zeige installierte Pakete (nur Dateinamen)
        -i      zeige installierte Pakete mit Version und Kurzbeschreibung
        -c      zeige Aenderungsgeschichte eines installierten Pakets
        -f      zeige Dateien eines installierten Pakets
        -p      zeige das installierte Paket, zu dem eine Datei gehoert
        -A      zeige angebotene Pakete (nur Dateinamen)
        -S      zeige angebotene Pakete (Server mit Dateinamen)
        -N      zeige angebotene nichtinstallierte Pakete (nur Dateinamen)
        -I      zeige angebotene Pakete eines Servers mit Informationen
-h, --help      diese Hilfe anzeigen und beenden
 --version      Versionsinformationen anzeigen und beenden
--show-config   Programmkonfiguration anzeigen und beenden
   --debug      Debug-Modus benutzen
        -q      nur mit Fehlermeldungen
        -v      mit vielen Meldungen
PAKET           Name des Pakets (auch Fragment)
DATEI		Name der Datei (auch Fragment)
URL		Server mit Protokoll und Verzeichnis mit abschliessendem /

EOT
return
}
#-----------------------------------------------------------------------------
function show_config ()
{
# Show configuration of program
# Uses: cat, cut, grep
# Return codes: standard

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_description: $# $@" >&2
	#$debuglog show_config: $# $@
fi

cat <<EOT

Konfigurierte Server:
EOT
for i in $UrlList; do
	echo "$i"
done
cat <<EOT

EOT

return
}
#-----------------------------------------------------------------------------
function show_all_local_files ()
{
# Show all local packages (complete file names)(needed for pkgmanager)
# Variables: llist
# Uses: cat, echo, rm, Build_Local_List
# Return codes:
# 0 = OK
# 2 = No packages found, config wrong

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_all_local_files: $# $@" >&2
	#$debuglog show_all_local_files: $# $@
fi

local ret=0

Build_Local_List
ret=$?							# ret: 0, 8
if [ $ret -eq 0 ]; then					# llist ok
	if [ "$verbose" == "-v" ]; then
		echo "Installierte Pakete:"
	fi
	cat $llist					# show package list
	ret=0
else							# llist not ok
	echo "Fehler - Keine installierten Pakete vorhanden!"
	ret=2
fi

rm -f $llist
return $ret
}
#-----------------------------------------------------------------------------
function show_all_local_info ()
{
# Show all local packages (name, version, description)
# Variables:
# Uses: echo, grep
# Return codes: standard

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_all_local_info: $# $@" >&2
	#$debuglog show_all_local_info: $# $@
fi

for i in $PROGREG/*.inf; do				# for every inf-file
	grep PKGNAME $i | cut -f 2
	grep VERSION $i | cut -f 2
	grep DESCRIPT $i | cut -f 2
	echo " "
done

}
#-----------------------------------------------------------------------------
function show_one_local_filelist ()
{
# Show .inf file of a searched installed package
# Par1: package name (fragments possible)
# Variables:
# Uses: cat, echo, grep, rm, Build_Local_List, Rebuild_Pkg_Filename, Pop_Stack
# Return codes:
# 0 = OK
# 1 = Wrong parameter
# 8 = File not found

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_one_local_filelist: $# $@" >&2
	#$debuglog show_one_local_filelist: $# $@
fi

local p1=$1 pkgfn="" lpn="" lvers="" lfnne="" n="" ret=0

Build_Local_List
grep -c "$p1" $llist > $tempfile			# test how many string founded
n=$(cat $tempfile)
if [ "$n" == "0" ]; then
	echo "Fehler - $p1 nicht gefunden - Angabe falsch!"
	rm -f $llist $tempfile
	return 1
elif [ "$n" == "1" ]; then
	grep "$p1" $llist > $tempfile			# search string in llist
else
	echo "Fehler - $p1 mehrmals vorhanden!"
	rm -f $llist $tempfile
	return 1
fi

pkgfn=$(cat $tempfile)
Rebuild_Pkg_Filename $pkgfn
Pop_Stack lpn
Pop_Stack lvers
Pop_Stack lfnne

if [ -e $PROGREG/$lpn.inf ]; then
	cat $PROGREG/$lpn.inf				# show file list
else
	echo "Fehler - $lpn.inf nicht gefunden!"
	ret=8
fi

rm -f $llist $tempfile
return $ret
}
#-----------------------------------------------------------------------------
function show_one_local_changelog ()
{
# Show changelog file of an installed package
# Par1: package name (fragment possible)
# Uses: cat, echo, grep, Build_Local_List, Rebuild_Pkg_Filename, Pop_Stack
# Return codes:
# 0 = OK
# 1 = Wrong parameter
# 8 = File not found

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_one_local_changelog: $# $@" >&2
	#$debuglog show_one_local_changelog: $# $@
fi

local p1=$1 pkgfn="" lpn="" lvers="" lfnne="" ret=0

Build_Local_List
grep -c "$p1" $llist > $tempfile			# test how many string founded
n=$(cat $tempfile)
if [ "$n" == "0" ]; then
	echo "Fehler - $p1 nicht gefunden - Angabe falsch!"
	rm -f $llist $tempfile
	return 1
elif [ "$n" == "1" ]; then
	grep "$p1" $llist > $tempfile			# search string in llist
else
	echo "Fehler - $p1 mehrmals vorhanden!"
	rm -f $llist $tempfile
	return 1
fi

pkgfn=$(cat $tempfile)
Rebuild_Pkg_Filename $pkgfn
Pop_Stack lpn
Pop_Stack lvers
Pop_Stack lfnne

if [ -e /usr/local/share/doc/packages/$lpn/ChangeLog ]; then
	echo ""
	echo "$lpn"
	cat /usr/local/share/doc/packages/$lpn/ChangeLog	# show changelog
else
	echo "Fehler - $lpn/ChangeLog nicht gefunden!"
	ret=8
fi

rm -f $llist $tempfile
return $ret
}
#-----------------------------------------------------------------------------
function show_local_package_of_file ()
{
# Show package that contain a given file
# Par1: file
# Uses: echo, grep
# Return codes:
# 0 = OK
# 8 = Package not found

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_local_package_of_file: $# $@" >&2
	#$debuglog show_local_package_of_file: $# $@
fi

local sfile=$1 ret=8

for i in $PROGREG/*.inf; do
	grep -q "$sfile" $i				# search for string in every inf file
	if [ $? -eq 0 ]; then
		echo ""
		grep "^PKGNAME" $i			# show pkg name
		grep "$sfile" $i			# show file
		ret=0
	fi
done
if [ $? -ne 0 ]; then
	echo "Fehler - Datei $sfile gehoert zu keinem Paket!"
fi

return $ret
}
#-----------------------------------------------------------------------------
function show_all_remote_url_files ()
{
# Show urls and all there packages (url, sorted filenames)
# Variables: rlist, UrlList
# Uses: cat, echo, rm
# Return codes:
# 0 = OK
# 2 = Config wrong
# 15= Not from all urls package list available

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_all_remote_url_files: $# $@" >&2
	#$debuglog show_all_remote_url_files: $# $@
fi

local ret=0 err=0

for s in $UrlList; do					# make for all urls
	Build_Remote_List $s				# build rlist
	ret=$?						# ret: 0, 2, 15
	if [ $ret -eq 0 ]; then
		echo ""
		echo "Auf $s vorhandene Pakete:"
		cat $rlist
	elif [ $ret -eq 2 ]; then
		echo "Fehler - unbekanntes Server-Protokoll, Konfiguration falsch!" >&2
		rm -f $rlist
		return 2
	else
		echo "Fehler - Von $s keine Paketliste vorhanden!"
		err=15
	fi
	rm -f $rlist
done

return $err
}
#-----------------------------------------------------------------------------
function show_all_remote_files ()
{
# Show all packages of urls (no url, filenames, sorted, no double)(needed for pkgmanger)
# Par1: [--noinstalled]
# Variables: rlist, tempfile, UrlList
# Uses: cat, cp, echo, rm, Build_Remote_List, Rm_Duplicate_Lines
# Return codes:
# 0 = OK
# 2 = Error in config
# 15= Not from all urls package list available

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_all_remote_files: $# $@" >&2
	#$debuglog show_all_remote_files: $# $@
fi

local p1=$1 tfile1=${tempfile}.sarf.1.tmp tfile2=${tempfile}.sarf.2.tmp ret=0 err=0

cp /dev/null $tfile1				# create tfile1
for s in $UrlList; do				# make for all urls
	Build_Remote_List $s			# build tempfile with packages (rlist)
	ret=$?					# ret: 0, 2, 15
	if [ $ret -eq 0 ]; then
		cat $rlist >> $tfile1		# put list at end of tfile1
	elif [ $ret -eq 2 ]; then		# error - config wrong - return
			echo "Fehler - $s hat unbekanntes Server-Protokoll, Konfiguration falsch!" >&2
		rm -f $rlist $tfile1
		return 2
	else					# error - server problem
		echo "Fehler - Von $s keine Paketliste vorhanden!"
		err=15
	fi
done
cat $tfile1 | sort | uniq > $tfile2		# sort tfile1 and rm duplicates
mv $tfile2 $tfile1				# rename tfile2
# wenn $1=--noinstalled ist, die installierten aussortieren
if [ "$p1" == "--noinstalled" ]; then
	Build_Local_List			# build tempfile with packages (llist)
	ret=$?					# ret: 0, 2
	if [ $ret -eq 0 ]; then
		grep -v -f $llist $tfile1	# rm installed packages and show package file names
	else					# llist not ok, config wrong
		echo "Fehler - Keine installierten Pakete vorhanden, Konfiguration falsch!"
		ret=2
	fi
else						# no --noinstalled given
	cat $tfile1				# show all package file names
fi

rm -f $rlist $llist $tfile1 $tfile2
return $err
}
#-----------------------------------------------------------------------------
function show_info_remote_server ()
{
# Show website on http-server, or README on ftp-server
# Par1: url (f.e. http://www.ingokaesmann.de/download/linux/)
# Variables: tempfile
# Uses: cat, echo, rm, wget, w3m
# Return codes:
# 0 = OK
# 15= Package list not from url available

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_info_remote_server: $# $@" >&2
	#$debuglog show_info_remote_server: $# $@
fi

local url prot tfileh tfilet
url=$1
prot=""
tfileh=$tempfile.sirs.html
tfilet=$tempfile.sirs.txt

prot=${url:0:4}						# server-protocol
if [ "$prot" == "ftp:" ]; then				# ftp:
	wget -q -nd -nH -O $tfileh ${url}README		# download README
	if [ "$?" -ne 0 ]; then
		echo "Fehler - Von $url keine Information herunterladbar!" > $tfileh
		ret=15
	fi
	cat $tfileh					# show README
elif [ "$prot" == "http" ]; then			# http:
	wget -q -nd -nH -O $tfileh ${url}		# load list from url
	if [ "$?" -ne 0 ]; then
		echo "Fehler - Von $url keine Information herunterladbar!" > $tfileh
		ret=15
	fi
	w3m -dump $tfileh > $tfilet			# build index file
	cat $tfilet					# show info file
fi

rm -f $tfileh $tfilet
}
##############################################################################
# PARSE COMMANDLINE

# Read all options with args and all additional args into variables.
# Stop parsing after last parameter.
# Try to do a check on all parameters and version numbers.
# Handle options -h, --show-config and -V directly.
# Exit on error.

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG Parse Commandline: $# $@" >&2
	#$debuglog Parse Commandline: $# $@
fi

# get options and options with arguments
while [ "${1:0:1}" == "-" ]; do				# get all options
	case "$1" in
		-h|--help)	opt=-h;;		# option -h
		--version)	opt=--v;; 		# option --version
		--show-config)	opt=--s;;		# option --show-config
		--debug)	debug=yes;;		# option --debug
		-q|--quiet)	verbose=-q;;		# option -q
		-v|--verbose)	verbose=-v;;		# option -v
#-------------------------- end of standard options --------------------------
	  -a|-c|-f|-i|-p|-A|-I|-N|-S)	opt="$1";;	# option -a,-c,-f,-i,-p,-A,-I,-N,-S
	  *)	if [ "$verbose" != "-q" ]; then
			echo "Fehler - Option $1 falsch!" >&2	# error
		else
			$errlog unknown option $1
		fi
		exit 1;;
	esac
	shift
	opt_found=yes
done

# handle standard options -h, -V, -C
case "$opt" in
  -h)	show_help; exit 0;;					# show help
  --v)	echo "$scriptname (${pkgname}) $version"; exit 0;;	# show version
  --s)	show_config; exit 0;;					# show config
esac

# check standard library
Compare_Version $lib_inka_std_sh_needed $Lib_Inka_Std_Sh_Version
ret=$?						# ret: 0,1,2,9,127
if [ $ret -eq 1 ]; then		# needed lib-version higher than installed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Programm benoetigt neuere Version von lib-inka-std.sh!" >&2
	else
		$errlog newer version of lib-inka-std.sh needed
	fi
	exit 3
elif [ $ret -eq 9 ] || [ $ret -eq 127 ]; then	# other error (version or lib missing)
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Versionspruefung von lib-inka-std.sh nicht moeglich!"
	else
		$errlog check of version of lib-inka-std.sh impossible
	fi
	exit 3
else					# check ok, reset $ret
	ret=0
fi

# check basis library
Compare_Version $lib_inka_basis_sh_needed $Lib_Inka_Basis_Sh_Version
ret=$?						# ret: 0,1,2,9
if [ $ret -eq 1 ]; then		# needed lib-version higher than installed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Programm benoetigt neuere Version von lib-inka-basis.sh!" >&2
	else
		$errlog newer version of lib-inka-basis.sh needed
	fi
	exit 3
elif [ $ret -eq 9 ]; then		# other error (version or lib missing)
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Versionspruefung von lib-inka-basis.sh nicht moeglich!"
	else
		$errlog check of version of lib-inka-basis.sh impossible
	fi
	exit 3
else					# check ok, reset $ret
	ret=0
fi

# check version of config files				# set config var!
Compare_Version $conf_file_needed $Inka_Basis_Conf
#Compare_Version $conf_file_needed $Program_Rc
ret=$?						# ret: 0,1,2,9
if [ $ret -eq 1 ]; then		# needed config-version higher than installed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - $scriptname benoetigt neuere Version der Konfig-datei!" >&2
	else
		$errlog newer version of conf file needed
	fi
	exit 2
elif [ $ret -eq 9 ]; then		# other error (version or conffile missing)
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Versionspruefung der Konfig-datei von $scriptname nicht moeglich!"
	else
		$errlog check of version of conf file impossible
	fi
	exit 2
else					# check ok, reset $ret
	ret=0
fi

# check arguments after options
case "$opt" in
  -c|-f|-p|-I)	if [ $# -eq 1 ]; then			# parameter count ok
				arg1="$1"
				shift
		else					# error in param count
			echo "Fehler - Parameteranzahl falsch!" >&2
			exit 1
		fi;;
  *)	if [ $# -ne 0 ]; then				# error in param count
		echo "Fehler - Parameteranzahl falsch!" >&2
		exit 1
	fi;;
esac
##############################################################################
# MAINPROGRAM

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG Main: $# $@" >&2
	#$debuglog Main: $# $@
fi

# Check what to do (initial options and args are removed from cmdline)
case "$opt" in
  -a)	show_all_local_files				# opt -a
	err=$?;;
  -c)	show_one_local_changelog $arg1			# opt -c
	err=$?;;
  -f)	show_one_local_filelist $arg1			# opt -f
	err=$?;;
  -i)	show_all_local_info				# opt -i
	err=$?;;
  -p)	show_local_package_of_file $arg1		# opt -p
	err=$?;;
  -A)	show_all_remote_files				# opt -A
	err=$?;;
  -I)	show_info_remote_server $arg1			# opt -I
	err=$?;;
  -N)	show_all_remote_files --noinstalled		# opt -N
	err=$?;;
  -S)	show_all_remote_url_files			# opt -S
	err=$?;;
  "")							# no option given
	echo "Fehler - Option fehlt!" >&2
	err=1;;
esac

exit $err
