#!/bin/bash
# Copyright (C) by Stefano Falsetto
# e-mail contact ....: mailto:stefko5@inwind.it
#
#    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
#
#
# WARNING: This script is bash2.x compatible.
#
# This is rot[t]log 
# Utility to archive, rotates, compresses, and mails system logs.
#
#


# Don't allow pressing CTRL+C (or sending SIGINT) during TEMPDIR generation
trap '' 2

# Following code is taken from:
# checkinstall v1.4.1 (c) Felipe Eduardo Sanchez Diaz Duran
# (with little changes)

# Find a safe TEMPDIR
BASE_TMP_DIR="/tmp"
TEMPDIR=${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 "$TEMPDIR" ] && rm -rf $TMP_DIR
if [ -e "$TEMPDIR" ]; then
   echo
   echo "My temp dir exists already."
   echo "This looks like a symlink attack!"
   echo
   echo "*** Aborting"
   echo
   exit 1
fi

mkdir $TEMPDIR
chmod 1700 $TEMPDIR
RETURN=$?

if [ $RETURN -gt 0 ]; then
   echo
   echo "**** Failed to create temp dir!"
   echo "**** Do you have write permission for ${BASE_TMP_DIR}?"
   echo
   echo '**** Aborting execution.'
   echo
   exit  $RETURN
fi

# Original code from stefko begin here :-)

# I think it's a good idea let to rottlog to ignore these signals, but
# if you beleave this is not useful, you can comment it out
trap '' 1 2 5 6

tmpfil=$TEMPDIR/rotttempfile.$$
NEWtmpFILE=$TEMPDIR/rottnewtmpfile.$$
PURGED_FILE=$TEMPDIR/rottpurgedfile.$$
TMPERR=$TEMPDIR/rotttemperr.$$
TMPERRMSG=$TEMPDIR/rotttempmsg.$$
trap 'rm -rf $TEMPDIR ; exit $USCITA' 0 

# ################################################################
# BEGIN INTERNAL VARIABLES
#
#         DON'T EDIT IF YOU DON'T KNOW WHAT YOU'RE DOING
# ################################################################

VERSION=0.20alpha
MAINPATH="/etc/rottlog"
MAINRC="$MAINPATH/rc"
DELAYED_FILES="$MAINPATH/.delayed_logs"
maxdepth=0
#DEBUG=1
MAIL=1

# Error codes
E_FILE_NOREAD=1
E_SYNTAX_ERROR=2 
E_BAD_LOGPART=3 
E_BAD_ENDSCRIPT=4 
E_BAD_CREATE=5 
E_BAD_ROTATE=6 
E_BAD_PARAM=7 
E_NO_STOREDIR=8 
E_CANT_CREATE=9
E_NO_PAGER=10
E_CANT_UNCOMPRESS=11
E_BAD_SIZE=12
E_BAD_MAXDEPTH=13

# Special values
BREAK_CYCLE=255

# ################################################################
# END INTERNAL VARIABLES
# ################################################################

debecho () {
  if [ ! -z "$DEBUG" ]; then
    echo "$1"
  fi
}

read_mainrc() {
  debecho "Reading main configuration file"
  if [ ! -e $MAINRC ]; then
    echo "Could'nt find main rc file!"
    USCITA=1
    exit $USCITA
  fi
  
  . $MAINRC
}

esegui_rotate() {

  # Il meccanismo di "delayed" funziona cos:
  # quando viene richiamata la rotazione si controlla se il nome del file
  # "$1" sta in DELAYED_FILES, se  cos viene compresso rimanendo sempre
  # con il nome preso da DELAYED_FILES, e si continua la procedura per il
  # prossimo file che sar solo "tagliato" se necessario ma non compresso.
  # Se il file "$1" non  presente in DELAYED_FILES si inserisce $2 in 
  # questo file, lo si copia in $2 e si prosegue con eventuali "tagli"

  # Se non c' DELAY allora prima si copia il log in un file temporaneo,
  # si comprime questo file temporaneo in $2, poi si applicano eventuali
  # tagli a $1. 

  # Gestisco la compressione a distanza di una rotazione...

  debecho "Processing file $1"
  #filesize=$(ls -l "$1" |tr -s ' '|cut -d' ' -f5)
  if [ ! -z "$notifempty" ] && [ "$size_b" -eq 0 ]; then
    debecho "Archive/rotation not necessary"
    return
  fi
  
  if [ ! -z "$DELAY" ]; then
    IS_OLD=$(grep "$1" $DELAYED_FILES 2>/dev/null)
    if [ ! -z "$IS_OLD" ]; then
      debecho "Compressing previously archived logfile"
      old_rotated=$(echo "$IS_OLD"|cut -d'=' -f2-)
      debecho "executing: cp -p "$old_rotated" $tmpfil"
      cp -p "$old_rotated" $tmpfil
      debecho "executing: $packer $compress "$tmpfil" >"$old_rotated" 2>$TMPERR"
      $packer $compress "$tmpfil" >"$old_rotated" 2>$TMPERR
      if [ $? -ne 0 ]; then
        (
        echo "Error in compress procedure. Command line was:"
        echo "$packer $compress \"$tmpfil\" \>\"$old_rotated\""
        echo "Error was:"
        cat $TMPERR
        ) > $TMPERRMSG
        return
      fi
      # Protegge ogni / con uno \: ddd/fff --> ddd\/fff
      ESCAPED=${1//\//\\/}
      sed -e "/^$ESCAPED/d" $DELAYED_FILES >$NEWtmpFILE
      cat $NEWtmpFILE >$DELAYED_FILES
    fi
    debecho "Updating delayed files archive"
    echo "$1=$2" >>$DELAYED_FILES
    cp -p "$1" "$2"
  else
    # Comprime il file direttamente se non c' delaycompress
    debecho "Compressing logfile"
    $packer $compress "$1" >"$2" 2>$TMPERR
    if [ $? -ne 0 ]; then
      (
      echo "Error in compress procedure. Command line was:"
      echo "$packer $compress \"$1\" \>\"$2\""
      echo "Error was:"
      cat $TMPERR
      ) > $TMPERRMSG
      return
    fi
  fi

  if [ -z "$bytes" ] && [ -z "$crit" ]; then
    if [ -z "$NOCREATE" ]; then
      debecho "creating new file"
      >$1
      if [ ! -z "$CHOWN" ]; then
        debecho "Changing own and perms to logfile"
        $CHOWN $1
        $CHMOD $1
      fi
    fi
    return
  fi

  debecho "Begin new logfile creation"
  # si copia...
  cp -pf "$1" $tmpfil

  quanti=$(wc -l $tmpfil|tr -s ' '|cut -d' ' -f-2)

  if [ -z "$bytes" ] || [ $bytes -eq 0 ]; then
    # Lascio le ultime linee, se necessario
    if [ -z "$qdldl" ] || [ $qdldl -eq 0 ]; then
      debecho "Keep logfile part beginning from regexp $crit"
      qdl=$(grep -n "$crit" $tmpfil|head -n 1|cut -d':' -f1)
      if [ -z "$qdl" ]; then
        debecho "Could'nt find regexp in logfile"
        qdl=0
      fi
      qdldl=$[ quanti - qdl + 1 ]
    fi
    if [ $quanti -le $qdldl ]; then
      debecho "Logfile tail is not necessary"
      return
    else
      debecho "Keep last $bytes lines of logfile"
      tail -$qdldl $tmpfil > "$1"
    fi
  else
    # Lascio gli ultimi bytes, se necessario
    if [ $quanti -lt $qdldl ]; then
      debecho "Logfile tail is not necessary"
      return
    else
      debecho "Keep last $bytes bytes of logfile"
      tail --bytes=$qdldl $tmpfil > "$1"
    fi
  fi

}

lastnum () {
  [ -z "$2" ] && local add=0 || local add=$2
  local taglia=${#1}
  local taglia=$[ taglia + 2 ]
  local lastnum=$[ $(ls -1 "$1"* 2>/dev/null|cut -b$taglia-|\
                   sort -n|tail -n 1) + $add ]
  if [ ! -z "$ROTATE" ] && [ $lastnum -gt "$ROTATE" ]; then
    lastnum=$(ls -1t "$1"* |cut -b$taglia-|tail -1)
  fi
  return $lastnum
}

prepare_rotate () {
  local orig_pcdpc="$pcdpc"
  for log in ${pcldr[@]}; do
    size_b=$(ls -l "$log"|tr -s ' '|cut -d' ' -f5)
    if [ ! -z "$MAXSIZE" ] && [ $size_b -le $MAXSIZE ]; then
      debecho "Filesize of logfile is less than MAXSIZE"
      debecho "logfile: $log"
      debecho "filesize=$size_b"
      debecho "MAXSIZE=$MAXSIZE"
      continue
    fi
    
    debecho "Restoring value of pcdpc..."
    pcdpc="$orig_pcdpc"
    debecho "Before expand_metavar pcdpc=$pcdpc"
    expand_metavar "$log" "$pcdpc"
    pcdpc="$expanded_metavars"
    debecho "After expand_metavar pcdpc=$pcdpc"
    if [ ! -d "$pcdpc" ] && [ ! -z "$CREATEDIR" ]; then
      debecho "Trying to make $pcdpc..."
      mkdir -p "$pcdpc" 2>/dev/null
    fi
    if [ ! -d "$pcdpc" ]; then
      echo "Directory to store compressed log does'nt exist!"
      echo "Log: ${pcldr[@]}"
      echo "Dir: $pcdpc"
      USCITA=$E_NO_STOREDIR
      exit $USCITA
    fi

    if [ ! -z "$param_storefile" ]; then
      debecho "Before expand_metavar:"
      debecho "storefile=$storefile"
      debecho "param_storefile=$param_storefile"
      expand_metavar "$log" "$param_storefile"
      storefile="$pcdpc/$expanded_metavars"
      debecho "After expand_metavar:"
      debecho "storefile=$storefile"
    else
      storefile="$pcdpc/$(basename $log)"
      lastnum "$storefile" 1
      numero=$?
      storefile="$storefile.$numero"
      debecho "Here storefile=$storefile"
    fi

    #storefile="$pcdpc/$(basename $log)"
    #lastnum "$storefile" 1
    #numero=$?
    debecho "First available extension number: $numero"
    # Aggiungiamo nome file e numero progressivo al pcdpc
    #storefile="$storefile.$numero"

    # Non  un gioco, solo elimino i doppi slash eventuali e li sostituisco
    # con uno singolo: ddd//bbb --> ddd/bbb
    storefile=${storefile//\/\//\/}

    if [ ! -z "$CHATTR" ]; then
      chattr -a "$log"
    fi

    # Eseguiamo lo script prima di ruotare
    debecho "Executing prerotate script"
    if [ -r "$TEMPDIR/prerotate.$$" ]; then
      # Here must be expanded metavars
      . $TEMPDIR/prerotate.$$
      > $TEMPDIR/prerotate.$$
    fi

    # Ruotiamo il log
    debecho "Rotating log"
    date_begin=$(date)
    esegui_rotate "$log" "$storefile"

    # Eseguiamo lo script dopo la rotazione
    debecho "Executing postrotate script"
    if [ -r "$TEMPDIR/postrotate.$$" ]; then
      # Here must be expanded metavars
      . $TEMPDIR/postrotate.$$
      > $TEMPDIR/postrotate.$$
    fi
    
    if [ ! -z "$CHATTR" ]; then
      chattr +a "$log"
    fi
    
    date_end=$(date)
    if [ ! -z "$MAIL" ]; then
      debecho "mailing to $touser action report"
      mail_to_admin $MAIL
    fi
  done
}

is_readable() {
  if [ ! -r "$1" ]; then
    echo "ERROR: Could'nt read logfile!"
    echo "Filename: $1"
    USCITA=$E_FILE_NOREAD
    exit $USCITA
  fi
}

is_quoted() {
  if [ $(expr index "$1" "\"" ) -eq 0 ]; then
    f=${1// /}
  else
    # Remove spaces from bottom of file after last " character
    # This syntax remove last " too (not only spaces), so I add it...
    f="${1//\" */}\""
  fi
}

is_wildcard() {
  # TODO: Check for all other special chars not protected by \ 
  # must be generated an error
  
  if [ $(expr index "$1" "\*" ) -eq 0 ]; then
    debecho "No wildcard in this filename"
    return 0
  else
    wild_filenames=$(find $1 -maxdepth $maxdepth)
    debecho "Found * in filename. Follows found files:"
    debecho "$wild_filenames"
    return 1
  fi
}

expand_metavar() {
  # If used two parameters:
  # First parameter $1 is logfile to be rotated/archived (with path)
  # Second parameter is string to expand
  # all metavariables can be expanded

  local tmpstr=

  local bname=$(basename "$1")		# @BASENAME
  local bdir=$(dirname "$1")		# @DIRNAME
  local year=$(date +%Y)		# @YEAR
  local month=$(date +%m)		# @MONTH
  local day=$(date +%d)			# @DAY
  local comp_ext="$extension"		# @COMP_EXT

  # Only if path is already expanded these two metavariables can be
  # sustituted.
  if [ $(expr index "$pcdpc" "\@") -eq 0 ]; then
    lastnum "$pcdpc/$bname" 1
    local next_ext=$?			# @NEXT_EXT
    local filename="$bname.$next_ext"	# @FILENAME
  fi

  # Substitute meta-variables with values:
  debecho "In expand_metavar:"
  debecho "1=$1"
  debecho "2=$2"
  tmpstr="$2"
  debecho "tmpstr before modify: $tmpstr"
  tmpstr=${tmpstr//\@BASENAME/$bname}
  tmpstr=${tmpstr//\@DIRNAME/$bdir}
  tmpstr=${tmpstr//\@YEAR/$year}
  tmpstr=${tmpstr//\@MONTH/$month}
  tmpstr=${tmpstr//\@DAY/$day}
  tmpstr=${tmpstr//\@COMP_EXT/$comp_ext}
  tmpstr=${tmpstr//\@NEXT_EXT/$next_ext}
  tmpstr=${tmpstr//\@FILENAME/$filename}

  debecho "tmpstr after all modifies: $tmpstr"

  expanded_metavars="$tmpstr"
}

analize_logpart () {
  # quanti bytes devono rimanere?
  qdldl="$1"
  local poschar=$[ ${#qdldl} - 1 ]
  local lastchar=$(echo "${qdldl:$poschar:1}"|tr 'a-z' 'A-Z')
  
  case "$lastchar" in
    L)
      # sono righe!
      righe=1
      bytes=0
      # elimino la 'L' finale
      qdldl=${qdldl:0:$poschar}
      debecho "Will keep last $qdldl rows"
      ;;
    B)
      # sono bytes!
      righe=0
      bytes=1
      # elimino la 'B' finale
      qdldl=${qdldl:0:$poschar}
      debecho "Will keep last $qdldl bytes"
      ;;
    \")
      #echo "E' una regexp!"
      # E' una regexp! (o gi di l...)
      # Elimino il primo e l'ultimo carattere, praticamente gli apici
      cr=${qdldl:1:$poschar-1}
      debecho "Here cr=$cr"
      if [ "$cr" = "#1 day" ]; then
        crit=$(LANG=en date "+%b")
        # Il primo del mese
        crit="$crit  1"
        debecho "Searching for $crit"
      else
        crit=$cr
      fi
      debecho "Will keep logfile rows beginning from first occurence of $crit"
      bytes=0
      qdldl=0
      ;;
    *)
      echo "Bad parameter!"
      debecho "bad lastchar=$lastchar"
      return 2
      ;;
  esac
  debecho "Here: bytes=$bytes, qdldl=$qdldl, righe=$righe, crit=$crit"
  return 0
}

read_and_do() { 
  if [ -z "$1" ]; then
    cmd_exec=( prepare_rotate )
  else
    cmd_exec=( $@ )
  fi
  sed -e '/^[[:space:]]*#.*/d' -e ' /^$/d' "$MAINPATH/$quale" >$PURGED_FILE
  while read LINEA; do
    local tmp=${LINEA// /}
    unset pcldr

    if [ "${tmp:${#tmp}-1}" != "{" ]; then
      echo "Syntax error in file $MAINPATH/$quale"
      USCITA=$E_SYNTAX_ERROR
      exit $USCITA
    fi
    # If there are multiple files to rotate with same rules
    filenames="${LINEA/{*/}"
    if [ $(expr index "$filenames" ",") -ne 0 ]; then
      index=0
      OLDIFS="$IFS"
      IFS=","
      for f in $filenames; do
        is_quoted "$f"
        is_wildcard "$f"
        if [ $? -eq 0 ]; then
          debecho "Normal fill of pcldr (commas)"
          is_readable "$f"
          pcldr[$index]="$f"
          index=$[ index + 1 ]
        else
          debecho "Wildcard filling (commas)"
          for f in $wild_filenames; do
            is_quoted "$f"
            is_readable "$f"
            pcldr[$index]="$f"
            debecho "Inserted file: ${pcldr[$index]}"
            index=$[ index + 1 ]
          done
        fi
      done
      IFS="$OLDIFS"
    else
      is_quoted "$filenames"
      is_wildcard "$f"
      if [ $? -eq 0 ]; then
        is_readable "$f"
        debecho "Normal fill of pcldr"
        pcldr[0]="$f"
      else
        for ff in $wild_filenames; do
          is_quoted "$ff"
          is_readable "$ff"
          pcldr[$index]="$ff"
          debecho "Wildcard filling"
          index=$[ index + 1 ]
        done
      fi
    fi
    debecho "Parsing options for: ${pcldr[@]}"
    read LINEA
    (
    while [ "$LINEA" != "}" ]; do
      # Dopo la prima riga (contenente { ) si analizzano le successive
      # la sintassi : <parola-chiave> <valore>
        
      set -- $LINEA
      debecho "Analyzing parameters of '$LINEA'"
      while [ $# -gt 0 ]; do
        case "$1" in
          storedir)
               if [ ${2:0:1} != "/" ]; then
                 pcdpc="$packdir/$2"
               else
                 pcdpc="$2"
               fi
               shift
               debecho "storedir parameter pcdpc=$pcdpc"
               ;;
          storefile)
               if [ -z $2 ]; then
                 echo "No store file specified!"
                 USCITA=$E_NO_STORENAME
                 exit $USCITA
               fi
               shift
               local params=$@
               param_storefile="$params"
               debecho "storefile parameter: param_storefile=$param_storefile"
               ;;
          logpart)
               shift
               # Due to a (probably) buggy 2.03.0(1) bash
               local params=$@
               debecho "params=$params"
               analize_logpart "$params"
               if [ $? -eq 0 ]; then
                 shift
               else
                 echo "Error in logpart parameter!"
                 USCITA=$E_BAD_LOGPART
                 exit $USCITA
               fi
               debecho "logpart parameter: parsing OK"
               LOGPART=1
               shift $#
               ;;
          nocompress)
               NOCOMPRESS=1
               debecho "using nocompress feature"
               ;;
          postrotate|prerotate)
               SCRIPTFILE=$TEMPDIR/$1.$$
               debecho "Writing $SCRIPTFILE"
               > $SCRIPTFILE
               chmod 700 $SCRIPTFILE
               read LINEA
               while [ "$LINEA" != "endscript" ]; do
                 debecho ">>> $LINEA"
                 echo "$LINEA" >>$SCRIPTFILE
                 read LINEA
               done
               debecho "End $SCRIPTFILE"
               ;;
          endscript)
               echo -n "This keyword must be used after a postrotate/prerotate"
               echo " definition!"
               USCITA=$E_BAD_ENDSCRIPT
               exit $USCITA
               ;;
          touser)
               touser="$2"
               debecho "touser parameter: touser=$touser"
               shift
               ;;
          create)
               if [ $# -ne 4 ]; then
                 echo "Error in create parameter!"
                 USCITA=$E_BAD_CREATE
                 exit $USCITA
               fi
               shift
               CHMOD="chmod $1"
               CHOWN="chown $2.$3"
               debecho "create parameter: CHMOD=$CHMOD +++ CHOWN=$CHOWN"
               shift 3
               ;;
          delaycompress)
               DELAY=1
               debecho "delaycompress parameter: DELAY=$DELAY"
               ;;
          ifempty)
               notifempty=
               debecho "ifempty"
               ;;
          notifempty)
               notifempty=1
               debecho "notifempty"
               ;;
          rotate)
               if [ -z "$2" ] || [ "$2" -lt 0 ] 2>/dev/null; then
                 echo "Bad rotate parameter"
                 USCITA=$E_BAD_ROTATE
                 exit $USCITA
               fi
               ROTATE=$2
               debecho "rotate parameter: ROTATE=$ROTATE"
               shift
               ;;
          size)
               # TODO: use b,k,M to allow specify bytes, kbytes and megabytes
               #       if any of this letters are used default is bytes.
               if [ -z "$2" ]; then
                 echo "no size parameter!"
                 USCITA=$E_BAD_SIZE
                 exit $USCITA
               fi
               # Remove last char
               lensize=${#2}
               MAXSIZE=${2:0:$lensize-1}
               if [ $MAXSIZE -lt 0 ]; then
                 echo "bad size parameter: Must be a valid number"
                 USCITA=$E_BAD_SIZE
                 exit $USCITA
               fi
               lastchar=${2:$lensize-1}
               case $lastchar in
                 k|K)
                   MULT=1024
                   ;;
                 m|M)
                   MULT=1000000
                   ;;
                 ""|b|B)
                   MULT=1
                   ;;
                 *)
                   echo "bad size identifier: Must be one of  k, M or b"
                   USCITA=$E_BAD_SIZE
                   exit $USCITA
               esac
               MAXSIZE=$[ MAXSIZE * MULT ]
               debecho "size parameter: MAXSIZE=$MAXSIZE"
               shift
               ;;
          nocreate)
               NOCREATE=1
               ;;
          createdir)
               CREATEDIR=1
               ;;
          append-only)
               CHATTR=1
               ;;
          maxdepth)
               if [ -z "$2" ] || [ "$2" -lt 0 ] >/dev/null; then
                 echo "Invalid maxdepth!"
                 USCITA=$E_BAD_MAXDEPTH
                 exit $USCITA
               fi
               shift
               maxdepth=$1
               ;;
          #mail)
          #     if [ "$2" = "log" ]; then
          #       MAIL=2
          #     fi
          #     ;;
          nomail)
               MAIL=
               ;;
          *)
               echo "Bad parameter!"
               debecho "Bad parameter: $1"
               USCITA=$E_BAD_PARAM
               exit $USCITA
               ;;
        esac
        shift
      done # sui campi della riga
      read LINEA
    done # sulle righe != }

    # SANITY CHECKS
    
    # 1) se c' delaycompress si ignora nocompress
    debecho "Ignoring nocompress if using delaycompress"
    if [ ! -z "$NOCOMPRESS" ] && [ -z "$DELAY" ]; then
      packer="cat"
      compress=
    fi
    if [ -z "$pcdpc" ]; then
      pcdpc="$packdir"
    fi
    if [ ! -z "$LOGPART" ] && [ ! -z "$CHOWN" ]; then
      echo "create option can't be used with logpart!"
      USCITA=$E_CANT_CREATE
      exit $USCITA
    fi
    # End of sanity checks

    # Here will call function specified in "$1" and all parameters
    ${cmd_exec[@]}
    EXIT_CODE=$?
    if [ $EXIT_CODE -ne 0 ]; then
      exit $EXIT_CODE
    fi

    )
    USCITA=$?
    debecho "Exit from subshell with errorcode: $USCITA"
    if [ $USCITA -ne 0 ] && [ $USCITA -ne $BREAK_CYCLE ]; then
      echo "There is an error in read cycle for configuration files"
      exit $USCITA
    elif [ $USCITA -eq $BREAK_CYCLE ]; then
      return
    fi
    #unset pcldr
  done <$PURGED_FILE
  
}

mail_to_admin() {

  # costruisco e mando il messaggio all'indirizzo stabilito
  #  echo "mando da $fromuser a $touser"
  if [ ! -z "$ROTATE" ]; then
    cosa="rotate"
    cosing="rotating"
  else
    cosa="archive"
    cosing="archiving"
  fi
  if [ ! -z "$qdldl" ]; then
    size_a=$(ls -l "$storefile"|tr -s ' '|cut -d' ' -f5)
  fi
  if [ -s "$TMPERRMSG" ]; then
    cat << EOF | $mail
From: $fromuser
To: $touser
Subject: Rot[t]Log $quale maintenance: ERROR report

Details of $quale log rotation NOT performed


File to $cosa           : $log

$( cat $TMPERRMSG )

Next rotation will be performed on $date_next (or so)
If you don't correct this problem before this date, will be sent same 
error message next time rottlog will try to manage this logfile.


---

Rot[t]Log v.$VERSION
  By Stefano Falsetto <stefko5@inwind.it>

EOF
  else
    cat << EOF | $mail
From: $fromuser 
To: $touser
Subject: Rot[t]Log $quale maintenance

Details of $quale log rotation performed:


File to $cosa		: $log
File ${cosa}d in	: $storefile
$(
  if [ ! -z "$qdldl" ]; then
    echo "Old filesize		: $size_b"
    echo "New filesize		: $size_a"
  fi
)
Log $cosing begin on	: $date_begin
Completed on		: $date_end

Next rotation will be performed on $date_next (or so)

---

Rot[t]Log v.$VERSION
  By Stefano Falsetto <stefko5@inwind.it>

EOF
  fi
   
  debecho "Sent mail from $fromuser to $touser"

}

check_last_rotate () {
  debecho "Checking for $3(ly) config file"
  if [ ! -e "$1" ]; then
    debecho "Making new control file: $1"
    echo "0">"$1"
    chmod 600 "$1"
  fi

  if [ -e "$1" ]; then
    chmod 600 "$1"
    last="$(cat "$1")"
    now="$(date +%s)"
    date_next="$(date --date "+1 $3")"   # "+%d/%m/%Y")"
    debecho "Old date  : $last"
    debecho "New date  : $now"
    debecho "Next date : $date_next"
    DIFFDATA=$[ now - last ];
    if [ $DIFFDATA -ge $2 ]; then
      debecho "$DIFFDATA >= $2"
      echo "$now">"$1"
      #echo "$date_next">"$1.next"
      return 1
    fi
  fi
  debecho "Rotation not needed: $DIFFDATA < $2"
  return 0  
}

read_daily() {

  quale="daily"
  if [ ! -e $MAINPATH/$quale ]; then
    debecho "Config file '$quale' does not exist"
    return
  fi

  check_last_rotate "$MAINPATH/.lastday" 86400 day
  if [ $? -eq 1 ]; then
    debecho "Rotating daily logfiles"
    read_and_do
  fi
   
}


read_monthly() {

  quale="monthly"
  if [ ! -e $MAINPATH/$quale ]; then
    debecho "Config file '$quale' does not exist"
    return
  fi

  check_last_rotate "$MAINPATH/.lastmonth" 2592000 month

  if [ $? -eq 1 ]; then
    debecho "Rotating monthly logfiles"
    read_and_do
  fi
   
}

read_weekly() {

  quale="weekly"
  if [ ! -e $MAINPATH/$quale ]; then
    debecho "Config file '$quale' does not exist"
    return
  fi

  check_last_rotate "$MAINPATH/.lastweek" 604800 week

  if [ $? -eq 1 ]; then
    debecho "Rotating weekly logfiles"
    read_and_do
  fi
      
}

banner() {
  echo "This is Rot[t]Log ver $VERSION"
  echo "Copyright (C) 2001 by Stefano Falsetto"
  echo "Rot[t]Log comes with ABSOLUTELY NO WARRANTY"

  if [ -z $1 ]; then
    return
  fi
  echo "This is free software, and you are welcome to redistribute it"
  echo "under certain conditions; This program is distributed in the"
  echo "hope that it will be useful, but WITHOUT ANY WARRANTY; without"
  echo "even the implied warranty of MERCHANTABILITY or FITNESS FOR A"
  echo "PARTICULAR PURPOSE. See the GNU General Public License"
  echo "for more details."
  echo
}

syntax () {
  banner
  echo
  echo "Syntax: rottlog <options>"
  echo "  --help, -h"
  echo "    Display this page and exit"
  echo "  --version, -V"
  echo "    Display version, disclamier and exit"
  echo "  --defaults"
  echo "    Display defaults values and exit"
  echo " --showlog <logfile>, -s <logfile>"
  echo "    Show with a pager uncompressed archived logs"
  echo " --summary <logfile>"
  echo "    Display a summary of some useful information about <logfile>"
  echo " --checkrc <what>,<what>,..."
  echo "    Check for syntax of specified configuration file(s)"
  echo "    <what> must be one of: daily, weekly, monthly, all"
  echo
}

show_defaults () {
  local VARS="MAINPATH MAINRC DELAYED_FILES MAIL pager DEBUG"
  local V=
  banner
  echo
  echo "Default values:"
  for V in $VARS; do
    echo -n "$V="
    eval echo \$$V
  done
}

show_log () {
  # In near future: infos about "$1" will be taken from config file
  ft=$(file -Lb "$packdir/$1"|grep -i "text")
  if [ ! -z "$ft" ]; then
    unpacker=cat
    uncompress=" "
    extension="txt"
  fi
  if [ ! -z "$pager" ]; then
    PAGER="$pager"
  fi
  if [ -z "$PAGER" ]; then
    PAGER=$(which less)
    if [ -z "$PAGER" ]; then
      PAGER=$(which more)
    fi
    if [ -z "$PAGER" ]; then
      echo "Can't find a pager! Use pager variable in main rc file or "
      echo "PAGER environnement variable"
      USCITA=$E_NO_PAGER
      exit $USCITA
    fi
  fi
  debecho "Using pager: $PAGER"
  if [ -z "$unpacker" ] || [ -z "$uncompress" ]; then
    echo "Bad configuration: use unpacker and uncompress variables in mail rc file"
    USCITA=$E_CANT_UNCOMPRESS
    exit $USCITA
  fi
  
  cp -f "$packdir/$1" $NEWtmpFILE.$extension
  debecho "Using: $NEWtmpFILE.$extension"
  
  if [ ! -r "$NEWtmpFILE.$extension" ]; then
    echo "Can't read logfile!"
    USCITA=$E_FILE_NOREAD
    exit $USCITA
  fi

  $unpacker $uncompress "$NEWtmpFILE.$extension" | $PAGER
}

findlog () {
  local log=
  local q=

  case $quale in
    monthly)
            q=month
            ADD=2592000
            ;;
    daily)
            q=day
            ADD=86400
            ;;
    weekly)
            q=week
            ADD=604800
            ;;
  esac

  debecho "q=$q +++ ADD=$ADD"
  debecho "Here pcldr=${pcldr[@]}"
  for log in ${pcldr[@]}; do
    if [ "$(basename $log)" = "$1" ]; then
      echo "Summary of logfile: $log"
      echo
      echo "storedir : $pcdpc"
      local now=$(date +%s)
      local last=$(cat "$MAINPATH/.last$q")
      local next=$[ last + ADD ]
      local secsdone=$[ now - last ]
      local secstodo=$[ next - now ]
      local daydone=$[ secsdone / 86400 ]
      local daytodo=$[ secstodo / 86400 + 1 ]
      local datedone=$( date --date "$daydone days ago" "+%a %x")
      local datetodo=$( date --date "++$daytodo days" "+%a %x")
      [ ! -z "$ROTATE" ] && cosa="rotate" || cosa="archive"
      echo
      if [ ! -z "$NOCOMPRESS" ]; then
        echo -n "${cosa}d logfile will NOT be compressed"
      else
        echo -n "${cosa}d logfile will be compressed"
      fi
      echo " with a $quale time interval"
      echo
      printf "Days elapsed from last rotation : %2d (%s)\n" $daydone "$datedone"
      printf "Days to wait for next rotation  : %2d (%s)\n" $daytodo "$datetodo"
      if [ ! -z "$DELAY" ]; then
        echo
        lastnum "$pcdpc/$(basename $log)"
        num=$?
        notcomp="$(basename $log).$num"
        echo "Filename of not yet compressed log: $notcomp"
        
      fi
      return $BREAK_CYCLE
    fi
  done
}

summarize_loginfo () {
  # ciclo tra daily, weekly, monthly
  # quando trovo il file in uno di questi tre visualizzo le info ed esco
  for quale in daily weekly monthly; do
    if [ -e $MAINPATH/$quale ]; then
      debecho "Searching in $quale conffile"
      read_and_do findlog "$1"
    fi
  done
}

checkrc () {
  # TODO: what appens with metaveriables???
  while [ $# -ne 0 ]; do
    if [ ! -e $MAINPATH/$1 ]; then
      echo "WARNING: $1 file does'nt exist!"
    else
      echo "Checking $1 configuration file..."
      quale=$1
      read_and_do /bin/true
      echo "Done."
    fi
    shift
  done
}

#####################################################################
#                               M A I N                             #
#####################################################################
if [ $# -ne 0 ]; then
  # For further expansion of code
  #while [ $@ -gt 0 ]; do
    case "$1" in
      --help|-h)
            syntax
            ;;
      --version|-V)
            banner 1
            ;;
      --defaults)
            show_defaults
            ;;
      --showlog|-s)
            read_mainrc
            if [ ! -r "$packdir/$2" ]; then
              echo "Logfile is not readable!"
              USCITA=$E_FILE_NOREAD
              exit $USCITA
            fi
            show_log "$2"
            ;;
      --summary)
            read_mainrc
            summarize_loginfo "$2"
            ;;
     --checkrc)
            shift
            if [ -z "$1" ]; then
              echo "Invalid syntax! You must use at least one of:"
              echo "main, weekly, monthly, daily, all"
            fi
            while [ $# -ne 0 ]; do
              case "$1" in
                weekly)
                    rctocheck="$rctocheck weekly"
                    ;;
                monthly)
                    rctocheck="$rctocheck monthly"
                    ;;
                daily)
                    rctocheck="$rctocheck daily"
                    ;;
                all)
                    rctocheck="weekly monthly daily" 
                    ;;
                *)
                  echo "Invalid option to checkrc: $1"
                  USCITA=$E_BAD_PARAM; exit $USCITA
                  ;;
              esac
              shift
            done
            read_mainrc
            checkrc $rctocheck 
            ;;
      --force)
            debecho "Deleting time control files"
            (
              for i in day month week; do
                debecho "Deleting $MAINPATH/.last${i}"
                rm -f "$MAINPATH/.last${i}"
              done
            )
            DONTEXIT=1
            ;;
      *)
            echo "Invalid parameter: $1"
            USCITA=$E_BAD_PARAM; exit $USCITA
            ;;
    esac
    shift
  #done
  [ -z "$DONTEXIT" ] && exit
fi
  
read_mainrc

read_monthly
read_weekly
read_daily

 
