#!/bin/bash
#
# Datenbank-Wartung.
#

function info
{
  echo -e '
  SYNTAX: tw_service [-c ext] [-u Objekt1,Objekt2,...] [-b] [-B] [-i]

  -c  Wählt die Konfiguration "tw.config-ext" an.
  -u  Aktualisiert die entsprechenden Einträge der Datenbank.
  -b  Sichert die mit BACKUP markierten Objekte.
      ( [!|=] Objekt [Auswahlmaske] [#Kommentar [BACKUP]] )
  -B  Wie "-b" mit anschließendem Update. (st_atime-Problem)
  -i  Nur interaktive Aktualisierung der Referenz-Datenbank.\n'
}

source ${0%/*}/tw_conf

DATABASE=tw.db_$HOSTNAME
DBSIG=tw.db_sig

function setentries
{
  # Liest markierte Einträge.
  unset -v entry
  h=$IFS ; IFS=${h:2:1} ; declare -i i=0
  for l in $(grep "#.*$1" $cf$ext); do
    entry[$i]=${l%% *} ; i=$((i+1))
  done
  IFS=$h
}

function error
{
  echo "--> ${0##*/}: $*" ; exit 1
}

function check_config
{
  if ! [ -e $cf$ext ] || ! [ -e $db$ext ] || ! [ -e $dbsig$ext ]; then
    error 'Keine gültige Konfiguration!'
  fi
}

function check_db
{
  if [ "$(< $dbsig$ext)" != "$($DESTDIR/siggen -7 $db$ext)" ]; then
    error 'Datenbank beschädigt!'
  fi
}

function go
{
  # Update!
  check_config ; check_db
  new_db="./databases/$DATABASE"
  [ -e $new_db ] && mv $new_db $new_db.tmp
  conf="--cfgfile $cf$ext --dbfile $db$ext"
  $DESTDIR/tripwire --quiet ${ext:+$conf} $*
  if [ $? = 1 ]; then
    [ -e $new_db.tmp ] && mv $new_db.tmp $new_db
    error 'Laufzeitfehler beim Update!'
  fi

  # Datenbank installieren!
  if [ -e $new_db ]; then
    cp -vp $new_db $db$ext ; chmod 600 $db$ext
    # Arbeitskopie...
    $DESTDIR/siggen -7 $new_db >$dbsig$ext ; chmod 600 $dbsig$ext
    #...zug. Signatur...
    gzip -1 -c $new_db >$dbback$ext.gz ; gzip -t $dbback$ext.gz
    # ...und Sicherheitskopie der Datenbank.
    end=".old"
  fi
  [ -e $new_db.tmp ] && mv $new_db.tmp $new_db$end
  unset end
}

# Optionen?
cf=$DESTDIR/tw.config ; db=$DATADIR/$DATABASE
dbsig=$DBSIGDIR/$DBSIG ; dbback=$BACKUPDIR/DATABASE
while getopts "c:u:bBih" opt; do
  case $opt in
    c) ext="-$OPTARG";;
    u) update=yes ; com_obj=${OPTARG//,/ };;
    b) backup=yes;;
    B) backup=yes ; update=yes ; backdate=yes;;
    i) unset backup update backdate ; intact=yes;;
    h) info ; exit 0;;
    *) exit 1;;
  esac
done

if [ -z "$*" ]; then
  info ; exit 1
fi

if [ "$backup" ]; then

  # Backup-Volumen integer?
  check_config ; check_db
  conf="-c ${ext#-}" ; $DESTDIR/tw_check ${ext:+$conf} >/dev/null
  [ $? = 1 ] && error 'Laufzeitfehler beim Integritätstest!'
  tail +"$(grep -n "Folgende Ver" $REPORT | tail -1 | sed -e 's/:.*//g')" $REPORT | \
  sed '/^[^adct]/d;/^$/d' >$REPORT.new
  setentries BACKUP
  for path in ${entry[*]}; do
    if grep -q $path $REPORT.new; then
      rm -f $REPORT.new
      error 'Backup nicht sinnvoll, da Inkonsistenzen vorhanden!'
    fi
  done
  rm $REPORT.new

  # Backup!
  if [ -n "${entry[*]}" ]; then
    eval find ${entry[*]} | cpio -o -V -H crc | gzip >"$BACKUPDIR/tw.archives$ext.gz"
    # Erzeugt ein SVR4-Archiv, das in BACKUPDIR deponiert wird. Die Rückübertragung ins
    # System kann einfach mit "gzip -d -c Archivname | cpio -i" erfolgen.
  fi
  back_obj=${entry[*]}

fi

if [ "$update" ]; then
  obj=$com_obj
  [ "$backdate" ] && obj="$obj $back_obj"
  [ "$obj" = " " ] && error 'Objekte spezifizieren!'
  go --update $obj
fi

if [ "$intact" ]; then
  if [ -z "$ext" ]; then
    h=$IFS ; IFS=${h:2:1} ; declare -i i=0
    for name in $(ls -d -1 $DESTDIR/tw.config*); do
      list[$i]=${name##*tw.config-}
      list[$i]=${list[$i]/*tw.config/<HARDCODED>}
      i=$((i+1))
    done
    IFS=$h ; PS3='Konfiguration? ' ; clear
    select cfg in ${list[*]}; do
      if [ "$cfg" ]; then
        [ $cfg != "<HARDCODED>" ] && ext="-$cfg"
        go --interactive ; unset ext
        read -p 'Weiterer Update? (j/n) '
        [ $REPLY = "n" ] && exit 0
      fi
      clear
    done
  else
    go --interactive
  fi
fi

