#! /bin/csh -f

alias usage 'echo Usage: `basename $0` "[ -nl ] [ -<past-backup-no> ] [ -R <root-directory> ] \" ; echo "               [ -h <backuphost> ]  <path-part> [ <path-parts> [ ... ] ]" ; echo "      " `basename $0` -a "[ -<past-backup-no> ] [ -R <root-directory> ] \" ; echo "               [ -h <backuphost> ]"; echo "      " `basename $0` "-{ef}  [ -R <root-directory> ] [ -h <backuphost> ] \" ; echo "               < <startup-info-file>" ;  exit 1'

if ($#argv < 1) then
  usage
endif

if (! $?BACKUP_HOME) then
  set pnam=$0
  set pnam = $pnam:t
  if ($pnam == $0) then
    foreach dir ($path)
      if (-x $dir/$0) then
	set p=$dir/$0
	break
      endif
    end
    if ($p == ./$pnam) then
      set p=`pwd`
      setenv BACKUP_HOME  $p:h
    else
      set p=$p:h
      setenv BACKUP_HOME  $p:h
    endif
  else
    if (./$pnam == $0) then
      set p=`pwd`/$pnam
    else
      if (`echo $0|cut -c1` != "/") then
        set p=`pwd`/$0
      else
        set p=$0
      endif
    endif
    set p=$p:h
    setenv BACKUP_HOME $p:h
  endif
endif

set path=($BACKUP_HOME/bin $path)
rehash

unsetenv AWK

# the solaris awk is doin' dawn f...... BS
foreach awk (nawk gawk awk)
  foreach dir ($path)
    if (-x $dir/$awk) then
      setenv AWK $dir/$awk
      break
    endif
  end
  if ($?AWK) break
end

if (! $?AWK) then
  echo 'No awk ? Is this really a lovely UNIX ?'
  echo 'Sorry. I have to exit.'
  exit 1
endif

set configfile=$BACKUP_HOME/lib/backup.conf

alias getparam $AWK' '"'"'/^[ 	]*'"'"'\!:1'"'"'/{split($0,a,"'"'"'\!:1'"'"'[ 	]*"); print a[2]}'"' $configfile"

set allf=/tmp/allf.$$
set spf=/tmp/spf.$$

set host="`getparam 'BackupHost:?'`"
set rootdir="`getparam 'RootDirectory:?'`"
set indexfilepart="`getparam 'IndexFilePart:?'`"
set numindexestostore="`getparam 'NumIndexesToStore:?'`"
set compresscmd="`getparam 'CompressCmd:?'`"
set uncompresscmd="`getparam 'UncompressCmd:?'`"
set logfile="`getparam 'LoggingFile:?'`"
set numparts="`getparam 'NumBackupParts:?'`"

if ("$uncompresscmd" == "" ) then
  set uncompresscmd=gunzip
endif

set list=0
set count=0
set prev=0
set unlink="u"
set all=0
set emergency_recovery=0
set filelist_recovery=0

set files=()

set oarg=""
foreach a ($argv)
  if ($oarg != "") then
    switch($oarg)
      case "R":
	set rootdir="$a"
	breaksw
      case "h":
	set host="$a"
	breaksw
    endsw

    set oarg=""
    continue
  endif

  if (`echo $a|grep '^[-][0-9][0-9]*$' |wc -l` > 0) then
    set prev=`echo $a|cut -c2-`
  else
    set opts=(`getopt ulnaefRh $a`)
    if ("_$opts[1]" != "_--") then
      foreach b ($opts)
        if ("_$b" == "_--") then
          break;
        endif
	switch ("_$b")
	  case "_-l":
            set list=1
	    breaksw
	  case "_-n":
            set count=1
	    breaksw
	  case "_-u":
            set unlink="u"
	    breaksw
	  case "_-a":
            set all=1
	    breaksw
	  case "_-f":
            set filelist_recovery=1
	  case "_-e":
            set emergency_recovery=1
	    breaksw
	  case "_-R":
	    set oarg="R"
	    breaksw
	  case "_-h":
	    set oarg="h"
	    breaksw
	  default:
	    set files=("$files" "$a")
        endsw
      end
    else
      set files=("$files" "$a")
    endif
  endif
end

if ($#files == 0 && ! $all && ! $emergency_recovery) then
  usage
endif

set estat=$status

onintr emexit

unalias cd

\rm -f $allf $spf

if ($emergency_recovery) then
  goto emergency_recovery
endif

set num=`cat $BACKUP_HOME/var/num`
@ num -= $prev >& /dev/null

if ($status != 0 || (! -e "$indexfilepart"$num && ! -e "$indexfilepart"$num".z")) then
  echo Sorry, no backup found with number "$num", exiting ...
  set estat=2
  goto emexit
endif

if (-e "$indexfilepart"$num) then
  set indexfiles="$indexfilepart"$num
else
  set indexfiles="$indexfilepart"$num".z"
endif
  
if ($numparts > 1) then
  if (-r $BACKUP_HOME/var/part) then
    set part=`cat $BACKUP_HOME/var/part`
    if (`echo $part|grep '[0-9][0-9]*'|wc -l` < 1) then
      set part=1
    endif
  else
    set part=$numparts
  endif
  if ($part < $numparts) then
    @ num--
    if (-e "$indexfilepart"$num) then
      set indexfiles=("$indexfilepart"$num $indexfiles)
    else
      set indexfiles=("$indexfilepart"$num".z" $indexfiles)
    endif
  endif
endif

if ($all) then
  goto backout_all
endif

echo -n Searching for files in backup ...

set pat='('`echo "$files"|awk '{for(i=1;i<NF;i++) printf "%s|",$i; printf "%s\n",$NF}'`')'
touch $allf
foreach idxfile ($indexfiles)
  if ($idxfile:e != "z") then
    grep -h '^[1-9][0-9]*[.][1-9][0-9]*:' $idxfile | egrep "$pat" >> $allf
  else
    cat $idxfile | $uncompresscmd | grep -h '^[1-9][0-9]*[.][1-9][0-9]*:' \
			| egrep "$pat" >> $allf
  endif
end


echo " done."

set numfiles=`cat $allf|wc -l`
if ($numfiles < 1) then
  echo Sorry, didn\'t find any matches. Nothing is backed out.
  set estat=3
  goto emexit
endif

echo -n Found $numfiles matches
set numfiles=(`awk '{print $1,$1}' $allf|tsort|wc -l`)
echo -n " in" $numfiles files
set numtapes=(`cut -d. -f1 $allf|awk '{print $1,$1}'|tsort|wc -l`)
echo " on" $numtapes tapes.

if ($count) goto emexit

if ($list) then
  cut -d" " -f2- $allf | more
  goto emexit
endif

echo Going to restore files.

set fault=0

while (1)
  set numfiles=`cat $allf|wc -l`
    if ($numfiles < 1) break
  \rm -f $spf
  set posspec=`head -1 $allf|cut -d: -f1`
  set actcart=`echo $posspec|cut -d. -f1`
  set actfile=`echo $posspec|cut -d. -f2`

  echo
  echo Extracting files from cartridge $actcart, file $actfile ...

  egrep '^'$actcart"."$actfile": " $allf | cut -d" " -f2- > $spf

  if (! -d $rootdir) then
    mkdir -p $rootdir
  endif

  cd $rootdir

  backup -xvg$unlink -T $spf -C $actcart -F $actfile -h $host

  if ($status != 0) then
    set fault=1
    echo " "
    echo Something went wrong backing out the files.
    echo See previous output for details.
  endif

  echo done with cartridge $actcart, file $actfile.

  \rm -f $spf
  egrep -v '^'$actcart"."$actfile": " $allf > $allf.new
  \mv -f $allf.new $allf
end

echo
if ($fault != 0) then
  echo " "
  echo Not all files have been backed out successfully.
  echo See previous output for details.
else
  echo All matching files successfully restored.
endif

emexit:

\rm -f $allf $spf $allf.new

exit $estat

backout_all:

if ($#indexfiles == 2) then
  if (! -e $indexfiles[1] && ! -e $indexfiles[2]) then
    echo Error: no logging files found. Extract the archive by hand.
    exit 91
  endif
endif
if ($#indexfiles == 1) then
  if (! -e $indexfiles) then
    echo Error: no logging files found. Extract the archive by hand.
    exit 91
  endif
endif

set newstart=`cat $indexfiles | head -1 | awk '{print $1}'`

set actcart=`echo $newstart | cut -d. -f1`
set actfile=`echo $newstart | cut -d. -f2 | cut -d: -f1`

while (1)
  if (! -d $rootdir) then
    mkdir -p $rootdir
  endif

  cd $rootdir

  echo -n Going to back out from cartridge $actcart, file $actfile ...

  backup -xvnau -h $host -F $actfile -C $actcart |& grep '^[1-9][0-9]*[.][1-9][0-9]*:' | tail -1 >! $spf

  set errst=$status
  set lastline=`cat $spf`
  \rm -f $spf

  if ($errst != 0) then
    echo -n " an error occured, trying to continue anyway ..."
  endif

  echo " done."

  set newstart=`echo $lastline | awk '{print $1}'`
  set lastfile=`echo $lastline | awk '{print $NF}'`
  set lastfilepat=`echo $lastfile | sed 's;/;\\/;g'`

  set nextline=`cat $indexfiles | sed '1,/^'$newstart'[ 	]*'"$lastfilepat"'$/ d' | grep '^[1-9][0-9]*[.][1-9][0-9]*:' | head -1`

  if (`echo $nextline|wc -w` < 1) then
    break
  endif

  set newstart=`echo $nextline | awk '{print $1}'`
  set actcart=`echo $newstart | cut -d. -f1`
  set actfile=`echo $newstart | cut -d. -f2 | cut -d: -f1`
end

if ($errst) then
  echo " "
  echo "The Backout ended with an error."
  echo "Try to analyze the logs on the backup-server."
  exit $errst
endif

exit 0


emergency_recovery:

# dummy line to make GNU sed happy
echo dummyline >! $allf
cat >> $allf

set num=`grep -i '^~~[	 ]*backup.*[1-9][0-9]*[	 ]*$' $allf |tail -1|awk '{print $NF}'`
if (`echo $num|grep '^[1-9][0-9]*$'|wc -l` < 1) then
  echo "Error: Cannot find necessary information for restore, sorry."
  exit 99
endif

set filenum=$num
set indexfiles="$indexfilepart"$filenum
while (-e $indexfiles || -e $indexfiles".z")
  echo "Warning: logging file $indexfiles exists, trying next number."
  @ filenum++
  set indexfiles="$indexfilepart"$filenum
end

touch $indexfiles
echo "Logging of the filenames goes to $indexfiles"
echo $filenum >! $BACKUP_HOME/var/num

set exitst=0

if (! -d $rootdir) then
  mkdir -p $rootdir
endif

cd $rootdir
while(1)
  if (`grep '^~~[ 	]*[Bb]ackup.*[ 	]*'$num'[ 	]*$' $allf|wc -l` == 0) then
    break
  endif

  sed '1,/^~~[ 	]*[Bb]ackup.*[ 	]*'$num'[ 	]*$/ d' $allf >! $spf
  \rm -f $allf
  set cart=`grep -i '^~~[ 	]*cartridge' $spf|head -1|awk '{print $NF}'`
  set file=`grep -i '^~~[ 	]*file' $spf|head -1|awk '{print $NF}'`
  mv $spf $allf
  if (`echo $cart|grep '^[1-9][0-9]*$'|wc -l` < 1) then
    echo "Error: Cannot find cartridge number, sorry."
    set exitst=99
    continue
  endif
  if (`echo $file|grep '^[1-9][0-9]*$'|wc -l` < 1) then
    echo "Error: Cannot find tape file number, sorry."
    set exitst=99
    continue
  endif

  if ($filelist_recovery) then
    echo "Going to restore filelist from cartridge $cart, file $file."
    backup -tn -h $host -F $file -C $cart >>& $indexfiles
    set s=$status
  else
    echo "Going to restore files from cartridge $cart, file $file."
    backup -xvnau -h $host -F $file -C $cart >>& $indexfiles
    set s=$status
  endif
  if ($s) then
    echo "An error occured. See the file $indexfiles for details."
  endif
end

\rm -f $allf $spf

exit $exitst
