#!/bin/bash
#
# installation logging tool
#
# This program is distributed under the terms of the 
# GNU GENERAL PUBLIC LICENSE Version 2 or later.
# see http://www.fsf.org and http://www.gnu.org for license details.
#
# $Id: ilog,v 1.4 2001/08/07 16:16:22 chris Exp root $
# (c) c.r. Tue Aug 22 17:16:52 MES 1995
# V 1.1 added check_lock() for file locking.
# V 1.2 c.r. Sun May  3 17:52:14 CEST 1998
#     make keywords case-insensitive
#     show keywords automatically
# V 1.3 c.r. Sun May  3 22:37:32 CEST 1998
#     batch ability for llink added 
# V 1.4 c.r. Fri Jul  3 18:08:19 CEST 1998
#     recognizes $EDITOR and $PAGER
# V 1.5 delta Mon Dec 17 10:51:34 CET 2001
#     Tue Aug  7 18:10:41 CEST 2001, chris
#     ilog setzt $LOGNAME und $USER auf $SUDO_USER, wenn vorhanden
# V 1.6 s.k.  Sun Dec  8 22:36:24 CET 2002
#     move installdb from /root/installdb to /etc/installdb
# V 1.7 s.k.  Sun Jun 22 12:06:17 CEST 2003
#     move installdb from /etc/installdb to /etc/ilog
# V 1.8 s.k.  Sun Jan 25 15:56:34 CET 2004
#     add ilogstdin, which reads a complete ilog entry from stdin 
#     remove redundant code
#     only the first keyword line is parsed (do not create ilog keywords
#        e.g. from security advisories which were pasted in ilog entry)
#     bugfix: if ilog db was empty, contents of current dir were shown
#        as keywords -> now empty
# 
# $Log: ilog,v $
# Revision 1.4  2001/08/07 16:16:22  chris
# catch sudo's $SUDO_USER
#
# Revision 1.3  1999/10/26 08:04:33  chris
# added support for getting messages from stdin (ilog -s) (works)
#
# Revision 1.2  1999/10/24 19:06:41  chris
# *** empty log message ***
#
# Revision 1.1  1998/08/03 15:01:39  chris
# Initial revision
#
#

INSTALLDB=/etc/ilog
I_RUD=$INSTALLDB/installed
I_ALL=$I_RUD.all
I_TMP=$I_RUD.tmp.$$
I_DEF=$INSTALLDB/keyword
LOCK=$INSTALLDB/.lock

LINE="----------------------------------------------------------------------"
umask 002

##
## view database
##
view_db () {
	if [ "$1" = "" ]; then
		${PAGER:-view} $I_ALL
	else
		${PAGER:-view} $I_RUD.$1
	fi
}

##
## list keys
##
list_keys () {
	for i in $(ls $I_RUD.*) ; do
		if [ $i != "$I_RUD.all" ]; then
			echo $i | sed "s#$I_RUD.##g" 
		fi
	done
}

##
## check for existence of a lock file
## used by: add_to_db()
##
check_lock () {
	while [ -f $LOCK ]; do
		sleep 1; 
	done
        echo $STAMP >> $LOCK
        read STAMP2 < $LOCK
        if [ "$STAMP" = "$STAMP2" ]; then
            echo "Database locked for me!"
            RETVAL=1
        else
	    echo "Someone else has locked the database!"
	    RETVAL=0
        fi
	return $RETVAL
}

##
## get keyword list
## expects: file to extract keyword line from
## returns: keyword list on stdout
##
get_keywords () {
	##
	## search first 'Keywords:'-line inside the header
	## remove "Keywords:" and "," ,
	## convert to lower case,
	## unify,
	## print that line and 
	## remove everything else.
	##
	KEYS=$(echo $(
		sed '1,/^Keywords:/{
				/^Keywords:/{ 
					s/^Keywords://
					s/,/ /g
					p
				}
			}
			d
			' $1 |\
                tr 'A-Z ' 'a-z\n' |\
                sort |\
                uniq
	))
	echo $KEYS
}

##
## add $I_TMP to db
## used by: main
## uses:    get_keywords()
##          check_lock()
##          $LOCK
##          $I_ALL
##          $I_TMP
##          $I_RUD
##
add_to_db () {
		
	STAMP=$(date "+%Y%m%d%H%M%S-$$")

	while check_lock ;  do 
		echo please be patient...
	done

	cat $I_TMP               >> $I_ALL

	KEYS=$(get_keywords $I_TMP)
	for i in $KEYS; do
		if [ $i != "all" ]; then
			cat $I_TMP >> $I_RUD.$i	 
		fi
	done
	rm -f $I_TMP
	rm -f $LOCK
}

##
## prompt the user for a subject, and start the editor for a new log entry
##
generate_edit_ilog_entry () {
	ALL_KEYS=$(echo $(list_keys)) ; export ALL_KEYS
	EXINIT=':map K :r! echo $ALL_KEYS
J'  ; export EXINIT

	echo -n "Subject: "
	read SUBJECT
	echo "$(date), $LOGNAME"   >> $I_TMP
	echo "Subject: $SUBJECT"   >> $I_TMP
	echo "Keywords: $ALL_KEYS" >> $I_TMP
	echo ""                    >> $I_TMP
	echo ""                    >> $I_TMP

	##
	## loop until Keywords: are set up correctly
	##
	KEYS_OK=""
	while [ "$KEYS_OK" = "" ]; do 

		##
		## edit tmp file
		##
		${EDITOR:-vi +$} $I_TMP

		##
		## get keyword list
		##
		KEYS=$(get_keywords $I_TMP)

		##
		## ensure that Keywords: line is not left unmodified
		##
		if [ "$KEYS" = "$ALL_KEYS" ]; then
			echo "ERROR: \"Keywords:\" line has not been edited"
			echo "If you really want to use all keywords please add \"all\" to the \"Keywords:\" line"
			sleep 3
			KEYS_OK=""
		else 
			KEYS_OK="1"
			##
			## check for new keys
			##
			for i in $KEYS; do
				if [ $i != "all" -a ! -e $I_RUD.$i ]; then
					echo "WARN:"
					echo "keyword '$i' unknown"
					echo "(e)dit ilog entry"
					echo "(v)iew existing keywords"
					echo "(a)add keyword description"
					read ANS
					case "$ANS" in
						v|V) for KW in $I_DEF.* ; do
							   echo ${KW%$I_DEF.}
							   sed 's/^/    /' $KW
							 done
							 KEYS_OK=""
							 ;;
						e|E) # go to re-editing
							 KEYS_OK="" 
							 ;;
						a|A) echo "# description for keyword '$i'" >> $I_DEF.$i
						     ${EDITOR:-vi +$} $I_DEF.$i
							 touch $I_RUD.$i
							 ;;
					esac
				fi
			done
		fi
		
	done

	echo $LINE                 >> $I_TMP
}

##
## read log entry from stdin
##
read_ilog_entry_from_stdin () {
	# if [ "$1" = "" ]; then	
	# 	echo "usage: ilog -s < file"
	# 	echo "       |ilog -s"
	# 	exit 1;
	#fi
	echo "$(date), $LOGNAME"                         >> $I_TMP
	cat                                              >> $I_TMP
	echo $LINE                                       >> $I_TMP
}

##
## generate log entry from LOCAL.config for installation
##
generate_LOCAL_inst_entry () {
	if [ "$1" = "" ]; then	
		echo "usage: ilog -l /path/LOCAL.config"
		echo "       iloglocal /path/LOCAL.config"
		exit 1;
	fi
	CONFIGFILE=$1
	DESCFILE=${CONFIGFILE%.config}.description
	KEYWORDS=$(grep "^Keywords: " $DESCFILE)
	SOFTWARE=$(grep "^Application.Name: " $DESCFILE |\
                   sed 's/^Application.Name: //' )
	VERSION=$( grep "^Application.Version: " $DESCFILE |\
                   sed 's/^Application.Version: //')

	echo "$(date), $LOGNAME"                         >> $I_TMP
	echo "Subject: $SOFTWARE $VERSION installed"     >> $I_TMP
	echo "$KEYWORDS"                                 >> $I_TMP
	echo ""                                          >> $I_TMP
	cat  $CONFIGFILE                                 >> $I_TMP
	echo $LINE                                       >> $I_TMP
}

##
## generate log entry from LOCAL.config for deinstallation
##
generate_LOCAL_deinst_entry () {
	if [ "$1" = "" ]; then	
		echo "usage: ilog -d /path/LOCAL.config"
		exit 1;
	fi
	CONFIGFILE=$1
	DESCFILE=${CONFIGFILE%.config}.description
	KEYWORDS=$(grep "^Keywords: " $DESCFILE)
	SOFTWARE=$(grep "^Application.Name: " $DESCFILE |\
                   sed 's/^Application.Name: //' )
        VERSION=$( grep "^Application.Version: " $DESCFILE |\
                   sed 's/^Application.Version: //')

	echo "$(date), $LOGNAME"                         >> $I_TMP
	echo "Subject: $SOFTWARE $VERSION de-installed"  >> $I_TMP
	echo "$KEYWORDS"                                 >> $I_TMP
	echo ""                                          >> $I_TMP
	echo "$SOFTWARE $VERSION de-installed"           >> $I_TMP
	echo $LINE                                       >> $I_TMP
}

##
## main program
##

## actual versions of sudo set LOGNAME and USER to root
## reset them to original values for logging purpose

if [ ! -z "$SUDO_USER" ]; then
	LOGNAME=$SUDO_USER
	USER=$SUDO_USER
	export LOGNAME USER
fi

case $(basename $0) in
	iview)
		view_db $1
		;;
	ikeys) 
		list_keys 
		;;
	iloglocal)
		generate_LOCAL_inst_entry $1
		add_to_db
		;;
	ilogstdin)
		read_ilog_entry_from_stdin
		add_to_db
		;;
	installed|ilog)
		case "$1" in 
			-v) ##
				## view database
				##
				view_db $I_ALL
				;;

			-k) ##
				## list keys
				##
				list_keys 
				;;
			-l) 
				shift
				generate_LOCAL_inst_entry $1
				add_to_db
				;;
			-d) 
				shift
				generate_LOCAL_deinst_entry $1
				add_to_db
				;;
			-s) 
				shift
				read_ilog_entry_from_stdin $1
				add_to_db
				;;
			"")
				generate_edit_ilog_entry
				add_to_db
				;;
		esac
		;;
esac

##
## EOF
##

