#!/bin/bash
# Copyright 2003, 2004 Stefano Falsetto <falsetto@gnu.org>
# Copyright 2008, 2010 David Egan Evans <sinuhe@gnu.org>
#
# This program is free software.  You can redistribute it, or modify it,
# or both, under the terms of the GNU General Public License version 3
# (or any later version) as published by the Free Software Foundation.
#
# 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, see <http://www.gnu.org/licenses>.
#

PREFIX="$HOME/src/rottlog/tmp"
ETCDIR="$PREFIX/etc/rottlog"
DEF_DIRMODE="755"
CONFIG_LOGROTATE="$PREFIX/etc/logrotate.conf" # /etc/logrotate.conf
BASE_TMP_DIR="$HOME/src/rottlog/tmp/log2rot"

# ERROR CODES
E_FILE_NOREAD=10
E_SYMLINK=11
E_CONFFILE=12

trap 'rm -rf $TEMPDIR ; exit $USCITA' 0
# Suppress C-c (SIGINT) during TEMPDIR generation
trap '' 2

debecho () {
	if test ! -z "$DEBUG"
	then
		echo "$1" >&2
	fi
}

expand_filenames () {
	# Filename expansion
	debecho "Begin filename expansion"
	if test $(expr index "$filenames" ",") -ne 0
	then
		index=0
		OLDIFS="$IFS"
		IFS=","
		for f in $filenames
		do
			is_quoted "$f" f
			is_wildcard "$f"
			if test $? -eq 0
			then
				debecho "Normal fill of pcldr (commas)"
				is_readable "$f" "$1"
				if test $? -eq 1
				then
					run_lastaction
					continue
				fi
				pcldr[$index]="$f"
				index=$[ index + 1 ]
			else
				debecho "Wildcard filling (commas)"
				for f in $wild_filenames
				do
					is_quoted "$f" f
					is_readable "$f" "$1"
					pcldr[$index]="$f"
					debecho "Inserted file: ${pcldr[$index]}"
					index=$[ index + 1 ]
				done
			fi
		done
		IFS="$OLDIFS"
	else
		is_quoted "$filenames" f
		is_wildcard "$f"
		if test $? -eq 0
		then
			is_readable "$f" "$1"
			if test $? -eq 1
			then
				run_lastaction
				continue
			fi
			debecho "Normal fill of pcldr"
			pcldr[0]="$f"
		else
			for ff in $wild_filenames
			do
				is_quoted "$ff" ff
				is_readable "$ff" "$1"
				pcldr[$index]="$ff"
				debecho "Wildcard filling"
				index=$[ index + 1 ]
			done
		fi
	fi
	debecho "End of filename expansion."
}

is_quoted() {
	local f="$1"
	if test $(expr index "$f" "\"" ) -eq 0
	then
		f=${f// /}
	else
		f=${f//\"/}
	fi
	eval $2=\"'$f'\"
}

is_readable() {
	if test ! -r "$1"
	then
		if test ! -z "$missingok" ] && [ "$2" != "log"
		then
			debecho "Missing? OK!"
			return 1
		else
			echo "ERROR: Could not read $2 file!"
			echo "Filename: $1"
			USCITA=$E_FILE_NOREAD
			exit $USCITA
		fi
	fi
	if test -L "$1" ] && [ $follow_symlinks -eq 0
	then
		echo "Can't follow symbolic links!"
		echo "Filename: $1"
		USCITA=$E_SYMLINK
		exit $USCITA
	fi
}

# This should be a library shared with rottlog.
make_tmpdir () {
        # Following code was taken from (with changes):
        # checkinstall v1.4.1 (c) Felipe Eduardo Sanchez Diaz Duran

        # Find a safe TEMPDIR
        [ ! -d $BASE_TMP_DIR ] && mkdir -p $BASE_TMP_DIR

        local tmpd=${BASE_TMP_DIR}/`awk 'BEGIN { srand(); for (i=1;i<21;i++) { a=95; while (a > 90 && a < 97) { a=65+int(50*rand())}; printf("%c", a) } }'`
        [ -e "$tmpd" ] && rm -rf "$tmpd"
        if [ -e "$tmpd" ]
        then
                echo
                echo "Aborting: A temporary directory exists already."
                echo
                exit 1
        fi

        mkdir $tmpd
        chmod 1700 $tmpd
        RETURN=$?

        if [ $RETURN -gt 0 ]
        then
                echo
                echo "Failed to create ${BASE_TMP_DIR}!"
                echo
                exit  $RETURN
        fi

        # Ignore these signals, but not critical.
        trap '' 1 2 5 6

        if [ -z "$1" ]
        then
                TEMPDIR="$tmpd"
                tmpfil=$TEMPDIR/rotttempfile.$$
                NEWtmpFILE=$TEMPDIR/rottnewtmpfile.$$
                PURGED_FILE=$TEMPDIR/rottpurgedfile.$$
                IFINCLUDE_FILE=$TEMPDIR/rottifincludefile.$$
                TMPERR=$TEMPDIR/rotttemperr.$$
                TMPERRMSG=$TEMPDIR/rotttempmsg.$$
                MAILMSG=$TEMPDIR/rotttempmsg.$$
                ROTATE_ATTACH=$TEMPDIR/rottateattach.$$
                ALL_ATTACH=$TEMPDIR/rotallattach.$$
                HANDLED=$TEMPDIR/rotthandled.$$
                TMPROTTCOLLECT=$TEMPDIR/rottmpcollect.$$
                TEMP_TARCOLL=$TEMPDIR/rotttarcol.$$
                TMP_ARCH_FILE=$TEMPDIR/rotttmparchfile.$$
                TMP_STATFILE=$TEMPDIR/rotttmpstatfile.$$
                NEW_TMP_STATFILE=$TEMPDIR/rottnewtmpstatfile.$$
                TMP_PERIOD_RC=$TEMPDIR/rotttmpperiodrc.$$
                TMP_ROTTMAXAGE=$TEMPDIR/rottmaxage.$$
        else
                eval "$1=\"$tmpd\""
        fi
}

trim() {
	local tmp=$(echo $1)
	eval $2=\"'$tmp'\"
}

write_to_file () {
	# extension?
	local fn=$1
	shift
	local cmd="$@"

	debecho "checking if starting a block"
	if test "${cmd//{/}" != "$cmd"
	then
		debecho "Starting a block!"
		debecho "Handling multiple file definitions."
		echo "${cmd// \//,/}" >>"$fn"
		debecho "Inserted ${cmd// \//,\/}"
	else
		(
		set -- $cmd
		case "$1" in
		copytruncate*|extension*|errors*|nocopytruncate|\
		include*|mailfirst)
			debecho "Commenting non-handled keyword: $cmd"
          		echo "# TODO: probably support $cmd" >>"$fn"
			shift $#
			;;
		daily|weekly|monthly)
			debecho "Ignoring keywords."
			shift
			;;
		mail)
			debecho "Mail translated to to user"
			echo "touser $2" >>"$fn"
			shift
			;;
		olddir)
			debecho "Olddir translated to storedir"
			echo "storedir $2" >>"$fn"
			shift
			;;
		noolddir)
			debecho "Noolddir translated to nostoredir"
			echo "nostoredir" >>"$fn"
			;;
		dateext)
			debecho "dateext translated using storefile"
			#echo "storefile @BASENAME.@NEXT_EXT-@YEAR@MONTH@DAY.@COMP_EXT" >> "$fn"
			echo "storefile @BASENAME.@NEXT_EXT-@YEAR@MONTH@DAY" >> "$fn"
			;;
		size*)
			debecho "Removing unused chars from size parameter."
			cmd="${cmd//=/ }"
			cmd="${cmd//+/ }"
			;;
		*)
			#debecho "write_to_file: Removing = chars..."
			#cmd="${cmd//=/ }"
			debecho "write_to_file: Recognized command: $cmd"
			echo "$cmd" >>"$fn"
			;;
		esac
		)
	fi
}

# MAIN
# Parameter handling
while test $# -gt 0
do
	case "$1" in
	-d|--debug)
		DEBUG=1
		;;
	-c|--conf)
		CONFFILE="$2"
		shift
		if test ! -f $CONFFILE
		then
			echo "Error: Supplied file doesn't exist!"
			exit $E_CONFFILE
		fi
		;;
	esac
shift
done

debecho "Making directory tree..."
make_tmpdir
if test -z "$CONFFILE"
then
	# Is it right to assume GZIP here?
	debecho "Setting default values."
	COMPRESS="-9c"
	UNPACKER="gunzip"
	PACKER="gzip"
	EXTENSION="gz"
	UNCOMPRESS="-c"
else
	source $CONFFILE
fi

mkdir -p $ETCDIR

for h in monthly weekly daily
do
	mkdir -p $ETCDIR/${h}.d
	chmod $DEF_DIRMODE $ETCDIR/${h}.d
done

# Devo leggere il file /etc/logrotate.conf e impostare:
# ROTATE
# MOWEDA
# MAILER
# TOUSER
# NOTIFEMPTY

# TODO
MAILER="/usr/sbin/sendmail -t"

BLOCK=
while read l
do
	trim "$l" l
	#ltrim "$l" l
	#rtrim "$l" l

	if test -z "$l" ] || [ "${l:0:1}" = "#"
	then
		continue
	fi
  
	if test $(expr "$l" : ".*}") -ne 0
	then
		if test -z "$block_rotate"
		then
			echo "rotate $ROTATE">>$TEMPDIR/block
		fi
		echo "$l">>$TEMPDIR/block
		debecho "End of block."
		cp $TEMPDIR/block $ETCDIR/${move_to}.d/$BLOCK_FILE
		block_rotate=
		BLOCK=
		continue
	fi
	if test ! -z "$BLOCK"
	then
		# TODO: non ignorare
		case "$l" in
		monthly|weekly|daily)
			move_to=$l
			continue
			;;
		rotate*)
			block_rotate=1
			;;
		esac
		debecho "Inserting: $l"
		echo "$l" >>$TEMPDIR/block
		continue
	fi
	if test $(expr "$l" : ".*{") -eq 0
	then
		debecho "Analyzing row -$l-"
		# Fuori dai blocchi di configurazione
		case "$l" in
		rotate*)
			ROTATE=${l:7}
			debecho "Default rotation period is: $ROTATE"
			;;
		monthly|weekly|daily)
			MOWEDA="$l"
			debecho "Default handling period is: $MOWEDA"
			;;
		errors*)
			TOUSER="${l:7}"
			debecho "Destination user is: $TOUSER"
			;;
		notifempty|ifempty)
			NOTIFEMPTY=${l:0:2}
			;;
		nocreate|create*)
			NOCREATE=${l:0:2}
			;;
		nocompress|compress)
			NOCOMPRESS=${l:0:2}
			;;
		compresscmd*)
			is_quoted ${l:12} PACKER
			;;
		uncompresscmd*)
			is_quoted ${l:14} UNPACKER
			;;
		compressext*)
			is_quoted ${l:12} EXTENSION
			;;
		compressoptions*)
			is_quoted ${l:16} COMPRESS
			;;
		include*)
			check="${l:8}"
			if test -d "$check"
			then
				INCLUDE_FILES="$INCLUDE_FILES $check/*"
			else
				INCLUDE_FILES="$INCLUDE_FILES $check"
			fi
			;;
		esac
	else
		BLOCK=1
		BLOCK_FILE=$(basename "$l"|rev|cut -d'{' -f2-|rev)
		debecho "Start block $l, BLOCK_FILE=$BLOCK_FILE"
		block_rotate=
		move_to=$MOWEDA
		echo "$l" >$TEMPDIR/block
	fi
done <$CONFIG_LOGROTATE

for p in monthly weekly daily
do
cat <<EOF >$ETCDIR/$p
# This configuration file is made automatically with log2rot $VERSION.
# Modify to meet your needs.

# $p configuration file for GNU Rot[t]Log
include $ETCDIR/${p}.d

EOF
done

LOCALHOST=$(domainname --fqdn)

cat <<EOF >$ETCDIR/rc
# Main configuration file for GNU Rot[t]Log
# These values can be overriden in monthly, weekly, and daily files
#
# This configuration file is made automatically with log2rot $VERSION.
# Modify to meet your needs.

# Compressor program
packer="$PACKER"

# Option to packer to compress and send to stdout
compress="$COMPRESS"

# DE-Compressor program
unpacker=$UNPACKER

# Option to decompressor to send output do stdout
uncompress="-c"

# Normal extension of compressed files (used in decompress ONLY)
extension="$EXTENSION"

# Pager used to view uncompressed logs
pager="less"

# Sender of mail messages
fromuser="rottlog@$LOCALHOST"

# Receiver of mail messages
touser="$TOUSER"

$(
	if test -z "$TOUSER"
	then
		echo "# Don't mail a report."
		echo "nomail"
	fi
)

# Mail program to send messages. Must be used option to read header recipient 
# addresses.
mail="$MAILER"

# Default Maximum depth to use with * metachar
maxdepth=0

# if set to 1 will follow symlinks
follow_symlinks=0

# Default mode, owner and group for newly created dirs (createdir parameter)
dir_perm=0700
dir_own=root
dir_grp=users

# Default mode, owner and group for newly created logfiles (create parameter)
fil_perm=0640
fil_own=root
fil_grp=users

# Silently remove from status file no longer existant delayed logfiles 
remove_missing

# Store archived logfiles in the same directory where "live" logfiles resides
nostoredir

# Copy mode, owner and group from old logfile if create is called without 
# parameters
create_logrotate

# Rotate files with logrotate method
log_rotate

EOF

(
	if test "$NOTIFEMPTY" = "no"
	then
		echo "# Use this to handle files of 0 size."
		echo "notifempty=1"
	fi
	if test "$NOCOMPRESS" = "no"
	then
		echo "# Don't compress old logfiles."
		echo "nocompress=1"
	fi
	if test "$NOCREATE" = "no"
	then
		echo "# Don't create empty logfile."
		echo "nocreate=1"
	fi
	echo
) >>$ETCDIR/rc

debecho "Here INCLUDE_FILES=$INCLUDE_FILES"

move_to=
if test ! -z "$INCLUDE_FILES"
then
	debecho "Including files."
	for i in $INCLUDE_FILES
	do
		bname=$(basename $i)
		debecho "Creating file $bname."
		> $TMPBLOCK
		while read 'line'
		do
			debecho "Reading row: $line"
			trim "$line" line
			debecho "After [l,r]trim: $line"
			case "$line" in
			"")
				continue
				;;
			rotate*)
				block_rotate=1
				;;
			*{)
				debecho "Here starting block: $line"
				> $TMPBLOCK
				block_rotate=
				;;
			})
				debecho "Here end a block..."
				if test -z "$move_to"
				then
					debecho "Moving in default period $MOWEDA."
					move_to=$MOWEDA
				fi
				if test -z "$block_rotate"
				then
					echo "rotate $ROTATE">>$TMPBLOCK
				fi
				echo "}">>$TMPBLOCK
				debecho "Appending TMPBLOCK to $ETCDIR/${move_to}.d/$bname."
				cat $TMPBLOCK >>$ETCDIR/${move_to}.d/$bname
				move_to=
				continue
				;;
			monthly|weekly|daily)
				move_to=$line
				;;
			esac
			debecho "Checking and inserting: $line"
			write_to_file $TMPBLOCK "$line"
		done<$i
	done
fi

