#!/bin/bash
#
# File: /usr/local/bin/buildpackage
#
# Build a tarball package
#
#    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.2
#
# 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
# 99= Other error
##############################################################################
# SOURCE FILES

. /usr/local/etc/main-inka-sh.conf			# main config
. $LLIBDIR/lib-inka-std.sh				# functions standard
. $LLIBDIR/lib-inka-basis.sh				# functions basis
. /usr/local/etc/inka-basis.conf			# global config
test -e /usr/local/etc/buildpackage.conf && . /usr/local/etc/buildpackage.conf	# global config
#. ~/.$(basename $0)rc					# personal config
#. ~/.xrc						# local config
##############################################################################
# DECLARATION OF VARIABLES

# STRINGS
pkgname=inka-buildpackage				# package name
lib_inka_std_sh_needed=1.3.6				# standard lib version
lib_inka_basis_sh_needed=1.3.3				# inka-basis lib vers.
conf_file_needed=0.3.2					# 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 -------------------------
make_tar="tar --owner=root --group=root -czf"		# make tar command
un_tar="tar --no-same-owner --wildcards -xpzf"		# untar command
inffile="pkg.inf"					# file of informations
opt_f=""						# option -f
opt_p=""						# option -p
arg1=""							# 1. arg from cmdline
pkgdir=$PackageDir					# package dir

# 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 [OPTION]... -l|-t
Aufruf: $scriptname [OPTION]... [-f] [-p]
Im 2. Fall wird ein Tarball-Paket erstellt und im Archiv gespeichert.

        -l      rekursive Ausgabe des aktuellen Verzeichnisinhalts
        -t      haengt Dateiliste an $inffile
        -f      kopiert fertiges PAKET ins ftp-Verzeichnis
        -p      kopiert fertiges PAKET ins Paketverzeichnis
-h, --help      Hilfe anzeigen und beenden
 --version      Versionsinformationen anzeigen und beenden
--show-config   Programmkonfiguration anzeigen und beenden
   --debug      Debug-Modus benutzen
        -q      ohne Meldungen
        -v      mit vielen Meldungen

Benutzer muss sich im gleichen Verzeichnis wie die Dateien befinden.

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

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

cat <<EOT

Archiv-Verzeichnis:
$Archdir

Archiv-Eigentuemer:
$Archown

ftp-Verzeichnis:
$Ftpdir

ftp-Eigentuemer:
$Ftpown

Paket-Verzeichnis:
$pkgdir

EOT

return
}

#-----------------------------------------------------------------------------
function main_proc ()
{
# Build package and store it in archiv dir.
# Possible is copy to ftp dir and or package dir.
# Par1: Complete filename of package
# Uses: cat, cd, chown, cp, echo, rm, tar, test, Rebuild_Pkg_Filename, Pop_Stack
# Return codes:
# 0 = ok
# 99= other error

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

local pfn d pname pvers fnne ret

pfn=""		# package file name
d=""		# actual date
pname=""	# package name
pvers=""	# package version
fnne=""		# file name without extension
ret=0

# add build date to pkg.inf
cat $inffile | grep -v '^BUILDDATE:' > $tempfile
d=$(date -R)
echo "BUILDDATE:	${d}" >> $tempfile
cp $tempfile $inffile
rm -f $tempfile

pfn=$(cat pkg.inf | grep '^FILENAME:' | cut -f 2)
$make_tar $Archdir/$pfn *		# make pkg and save it in archiv dir
ret=$?
if [ "$ret" -eq 0 ]; then		# pkg saved
	chown $Archown $Archdir/$pfn		# change owner of stored pkg
	if [ -n "$opt_f" ]; then		# option -f set
		cp $Archdir/$pfn $Ftpdir	# cp pkg to ftp server dir
		chown $Ftpown $Ftpdir/$pfn	# change owner of pkg in ftp dir
	fi
	if [ -n "$opt_p" ]; then		# option -p set
		Rebuild_Pkg_Filename $pfn	# decomposite filename
		Pop_Stack pname
		Pop_Stack pvers
		Pop_Stack fnne
		test ! -e $pkgdir/$fnne && mkdir $pkgdir/$fnne	# create dir if not exist
		if [ -d $pkgdir/$fnne ]; then	# dir exist
			cd $pkgdir/$fnne		# cd to pkg dir
			rm -fr *			# rm all in pkg dir
			cp $Archdir/$pfn .		# cp pkg to pkg dir
			$un_tar $pfn			# unpack pkg
		else				# dir not exist, creating not possible
			if [ "$verbose" != "-q" ]; then
				echo "Fehler - Verzeichnis $pkgdir/$fnne konnte nicht erstellt werden!" >&2
			else
				$errlog creating $pkgdir/$fnne not possible
			fi
			ret=99
		fi
	fi
else					# make_tar failed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - $make_tar $Archdir/$pfn misslungen!" >&2
	else
		$errlog $make_tar $Archdir/$pfn failed
	fi
	ret=99
fi

rm -f $tempfile
return $ret
}
#-----------------------------------------------------------------------------
function tree_write ()
{
# Write a listing with tree from actual dir to inffile
# Par1: Complete file name of package
# Uses cat, cut, echo, grep, rm, sed, tree
# Return codes:
# 0 = ok
# 99= other error

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

local p1="$1" s="" ret=0

# file name
s=$(cat $inffile | grep -m 1 '^PKGNAME:' | cut -f 2)

# change ./docs to /usr/local/share/doc/packages/<pkg>
SEDCMD0="s/\.\/doc/\/usr\/local\/share\/doc\/packages\/${s}/g"

# change ./lshare to /usr/local/share/<pkg>
SEDCMD1="s/\.\/lshare/\/usr\/local\/share\/${s}/g"

# change ./lbin to /usr/local/bin
SEDCMD2="s/\.\/lbin/\/usr\/local\/bin/g"

# change ./rbin to /root/bin
SEDCMD3="s/\.\/rbin/\/root\/bin/g"

# change ./rc to /etc/init.d
SEDCMD4="s/\.\/rc/\/etc\/init\.d/g"

# change ./llib to /usr/local/lib/sh
SEDCMD5="s/\.\/llib/\/usr\/local\/lib\/sh/g"

# change ./letc to /usr/local/etc
SEDCMD6="s/\.\/letc/\/usr\/local\/etc/g"

# change ./man1 to /usr/local/man/man1
SEDCMD7="s/\.\/man1/\/usr\/local\/man\/man1/g"

# change ./man8 to /usr/local/man/man8
SEDCMD8="s/\.\/man8/\/usr\/local\/man\/man8/g"

# change ./etc to /etc
SEDCMD9="s/\.\/etc/\/etc/g"

# change ./syscnf to /etc/sysconfig
SEDCMD10="s/\.\/syscnf/\/etc\/sysconfig/g"

# change ./ivman to /etc/ivman
SEDCMD11="s/\.\/ivman/\/etc\/ivman/g"

# change ./udev to /etc/udev/rules.d
SEDCMD12="s/\.\/udev/\/etc\/udev\/rules\.d/g"

# change ./crond to /etc/cron.d
SEDCMD13="s/\.\/crond/\/etc\/cron\.d/g"

# change ./ulib to /usr/lib
SEDCMD14="s/\.\/ulib/\/usr\/lib/g"

# build dir tree, rm ./help* ./install.sh ./pkg.inf
tree -f -i --noreport -p -s -u -g -D --dirsfirst \
	| grep -v './help' | grep -v './install.sh' \
	| grep -v './pkg.inf' | grep -v '^.$' > $tempfile

# change entries
cat $tempfile | sed -e $SEDCMD0 | sed -e $SEDCMD1 | sed -e $SEDCMD2 \
	| sed -e $SEDCMD3 | sed -e $SEDCMD4 | sed -e $SEDCMD5 \
	| sed -e $SEDCMD6 | sed -e $SEDCMD7 | sed -e $SEDCMD8 \
	| sed -e $SEDCMD9 | sed -e $SEDCMD10 | sed -e $SEDCMD11 \
	| sed -e $SEDCMD12 | sed -e $SEDCMD13 | sed -e $SEDCMD14 >> $inffile
ret=$?
if [ $ret -ne 0 ]; then ret=99; fi

rm -f $tempfile
return $ret
}
##############################################################################
# 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, -C 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 --------------------------
	  -l|-t)	opt="$1";;			# option -l, -t
	  -f)	opt_f=$1;;				# option -f
	  -p)	opt_p=$1;;				# option -p
#	  -z)	opt_z=$1				# option -z + 1 arg
#		if [ "$#" -gt 1 ] & [ "${2:0:1}" != "-" ]; then	# par2 is 1.arg of opt_z
#			opt_z1=$2
#			shift				# shift option
#		else					# error no arg
#			if [ "$verbose" != -q ]; then
#				echo "Fehler - Wert fuer Option $1 fehlt!" >&2
#			else
#				$errlog arg for option $1 is missing
#			fi
#			exit 1
#		fi;;
	  *)	if [ "$verbose" != "-q" ]; then
			echo "Fehler - Option $1 falsch!" >&2	# error
		else
			$errlog unknown option $1
		fi
		exit 1;;
	esac
	shift			# shift option, or last argument for option
	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 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 library
Compare_Version $lib_inka_basis_sh_needed $Lib_Inka_Basis_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 ]; 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 version of config files				# set config var!
Compare_Version $conf_file_needed $Buildpackage_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 of 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
#  -x|-y|-z)	if [ $# -eq 1 ]; then		# parameter count ok
#				arg1="$1"
#				shift
#		else				# error in param count
#			if [ "$verbose" != "-q" ]; then
#				echo "Fehler - Parameteranzahl falsch!" >&2
#			else
#				$errlog parameter count wrong
#			fi
#			exit 1
#		fi;;
  *)	if [ $# -ne 0 ]; then				# error in param count
		if [ "$verbose" != "-q" ]; then
			echo "Fehler - Parameteranzahl falsch!" >&2
		else
			$errlog parameter count
		fi
		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
  "")							# make package
	main_proc
	err=$?;;
  -l)							# output actual dir
	tree --dirsfirst
	err=$?;;
  -t)							# write file list to inffile
  	tree_write $arg1
  	err=$?;;
esac

exit $err
