:
#  Title : Sicherung des gesamten Systems.
#          Entweder auf das angebene Device oder defaultmaessig auf ein 
#	   Spulen-Magnetband.
#  Created      :       Thu, 08-Feb-90 / 10:47 / (pf)
#  Version      :       Thu, 17-Jul-97 / 11:03 / (pf,rb,mk+)
#
# einige nuetzliche Bourne Shell Prozeduren
#
# PROCEDURE Yes : Prompt for yes or no answer - returns non-zero for no
Yes() {
	while	read yn
	do	case $yn in
		       [yYjJ])	return 0 	;;
		       [nN])	return 1	;;
		       *) Error 1
		       ;;
		esac
	done
}

#
# PROCEDURE Error (msgNum : CARDINAL);
Error() {
	PARAM=$1
	(echo "\007\c"; Print saveSystem 2;
	 echo " : "; PrintLn saveSystem ${PARAM}) >&2
	return 1
}


BlockNotify()
{
  myMsg=`BlockPrint $1 $2`
  if   [ -n "$isTerm" ]
  then echo "$myMsg"; read dummy
  else echo "$myMsg" | Notify
  fi
}

MsgNotify()
{
  myMsg=`GetMsg saveSystem 3`
  if   [ -n "$isTerm" ]
  then echo "$myMsg"; read dummy
  else echo "$myMsg" | Notify
  fi
}

#
# PROCEDURE ComputeNBlocks(dev:ARRAY OF CHAR)
#     Setzt die Environment-Variable $nBlocks auf die Anzahl von
#   5k-Bloecken, die auf das verwendete Tape passen.
ComputeNBlocks()
{ 
  dev=$1
  case $dev in
       *rmt*)
	   # Auf ein 2400ft-Band passen ca. 115MB (cpio -B). Diese Parameter
	   # werden benutzt, um nach Abfrage der Bandlaenge die Kapazitaet zu
	   # berechnen.
	   #> Bitte denken Sie daran, dass bei Verwendung mehrerer
	   #> Baender alle die gleiche Laenge haben muessen. Sie
	   #> brauchen im unguenstigsten Fall ca. 4000 ft Band.
	   BlockPrint saveSystem rmtSpecial
	   KBperFt=51
	   nBlocks=
	   while [ -z "$nBlocks" ]
	   do  : #> Laenge pro Bandspule in ft ? [2400]
	       GetMsg saveSystem rmtTapeLen
	       [ -n "$isTerm" ] && read ftLen
	       [ "$ftLen" ] || ftLen=2400
	       if   [ "$ftLen" -lt 400 ] || [ "$ftLen" -gt 4000 ]
	       then : #> Unplausible Eingabe (Bandlaenge 400-4000 ft)
		    GetMsg saveSystem rmtTapeLenErr
	       else nBlocks=`expr $ftLen \* $KBperFt`
	       fi
	   done
	   ;;
       *exa*)
           nBlocks=409600 #--- 2GB (also 112m Tape)
	   return 0
	   ;;
       *)  if   [ "$OS" = "SCOSV" ] || [ "$OS" = "XENIX" ]
           then nBlocks=57548 #--- 281MB Optical
                return 0
           fi
           set -- `scsi $dev capacity` || return 1
	   if   [ "$2" != 512 ]
	   then GetMsg saveSystem illBlockSize #--- Nur 512 Bytes pro Block...
	        return 1
	   fi
	   nBlocks=`expr $1 / 2`
	   ;;
  esac
  #--- ganzzahliges Vielfaches von 5k (wg. cpio -B)
  nBlocks=`expr $nBlocks / 5`   #; nBlocks=`expr $nBlocks \* 5`;
  echo ""
  return 0
}


#
# PROCEDURE DDDevOut(dev:ARRAY OF CHAR; nBlocks:CARDINAL;
#                    msg:ARRAY OF CHAR)
DDDevOut()
{ 
  dev=$1; nBlocks=$2; msg="$3"
  volNum=1;
  tmpFile=/tmp/sS$$
  cpio -oc${VERBOSE}B |
  while dd of=$dev bs=5120 count=$nBlocks 2>$tmpFile
  do blocks=`cat $tmpFile`; rm -f $tmpFile
     blocks=`expr match "$blocks" "\([0-9]*\)"`
     if   [ "$blocks" != $nBlocks ] || [ "$blocks" = "0" ]
     then : # Band nicht ganz voll - kann nur letztes sein
          break;
     fi
     echo ""
     volNum=`expr $volNum + 1`
     if   [ -n "$isTerm" ]
     then (echo "$msg" | sed s/%d/$volNum/ >/dev/tty) </dev/null
          read dummy </dev/tty
     else (echo $msg | sed s/%d/$volNum/ | Notify) </dev/null
          result=$?
     fi
  done
  rm -f $tmpFile
  return 0
}


#
# PROCEDURE WriteTape(dev:ARRAY OF CHAR; nBlocks:CARDINAL; msg:ARRAY OF CHAR)
WriteTape()
{ 
  dev=$1; nBlocks=$2; msg="$3"

  #> Legen Sie bitte ein freies Band ein und druecken Return
  BlockNotify saveSystem 3

  #> Alle Dateien im Verzeichnis '/' und darunter werden gesichert...
  #> Das kann ein Weilchen dauern.\n
  #> Sollte mehr als ein Band erforderlich werden, sollten Sie bei
  #> Aufforderung ein neues Band einlegen und dann <ENTER> druecken.\n
  #> Es empfiehlt sich, Baender sofort nach der Entnahme zu beschriften !\n
  BlockPrint saveSystem 7

  [ -n "$isTape" ] && mtape fname $dev rew

  cd /

  case $OS in 
       SCOSV|XENIX) 
	   sysDirs=.
	   ;;
       IRIX) 
           sysDirs=.
           if   mount | grep "on /usr " >/dev/null
           then sysDirs="$sysDirs ./usr"
           fi
           if   mount | grep "on /var " >/dev/null
           then sysDirs="$sysDirs ./var"
           fi
           if   mount | grep "on /opt " >/dev/null
           then sysDirs="$sysDirs ./opt"
           fi
           ;;
       SunOS)
           sysDirs="."
           if   mount | grep "^/usr " >/dev/null
           then sysDirs="$sysDirs ./usr"
           fi
           if   mount | grep "^/var " >/dev/null
           then sysDirs="$sysDirs ./var"
           fi
           if   mount | grep "^/opt " >/dev/null
           then sysDirs="$sysDirs ./opt"
           fi
	   ;;
       *)  GetMsg saveSystem unsupportedOS
           false
           return
           ;;
  esac

  homeDirs=
  for homeDir in `awk -F: '$6 ~ /^\/projects\// {print $6}' /etc/passwd`
  do  [ -d "$homeDir" ] && homeDirs="$homeDirs .$homeDir"
  done

  echo "\nSystem : $sysDirs"
  echo "Home   : $homeDirs\n"

  case $OS in
      IRIX)   ( /bin/find $sysDirs -mount -print;
		/etc/mount | awk '{print $3}' #--- Mountpoints
		for dir in $homeDirs
		do  ls -d $dir
		    ls -d1 $dir/.??* 2>/dev/null
		done
	      ) | DDDevOut $dev $nBlocks "$msg"
	      ;;
      SCOSV) ( /bin/find $sysDirs -mount -print;
	       /etc/mount | awk '{print $1}' #--- Mountpoints
	       for dir in $homeDirs; do
	           ls -d $dir
		   ls -d1 $dir/.??* 2>/dev/null
	       done
	      ) | DDDevOut $dev $nBlocks "$msg"
	      ;;
      SunOS) ( /bin/find $sysDirs -mount -print;
	       /etc/mount | awk '{print $1}' #--- Mountpoints
	       for dir in $homeDirs; do  
	           ls -d $dir
		   ls -d1 $dir/.??* 2>/dev/null
	       done
	      ) | DDDevOut $dev $nBlocks "$msg"
	      ;;
      XENIX) delim=
	     filter=
	     for mountPoint in `/etc/mount | awk '{print $3}'`; do  
		 if [ "$mountPoint" != '/' ]
		 then filter="$filter$delim^\\.$mountPoint/"
		      delim="|"
		 fi
	     done
	     (find . -print | egrep -v $filter
	       for dir in $homeDirs
	       do  ls -d $dir
		   ls -d1 $dir/.??* 2>/dev/null
	       done
	      ) | cpio -oca${VERBOSE}B -K $nBlocks -M "$msg" -O $dev
	      ;;
  esac

  if   [ -n "$isTape" ]
  then mtape fname $dev rew
  else true;
  fi
}

#
# PROCEDURE DDDevIn(dev:ARRAY OF CHAR; nBlocks:CARDINAL;
#                   msg:ARRAY OF CHAR; nTapes:CARDINAL)
DDDevIn()
{ 
  dev=$1; nBlocks=$2; msg="$3"; nTapes=$4
  volNum=1;
  tmpFile=/tmp/sS$$
  while dd if=$dev count=$nBlocks bs=5120 2>$tmpFile
  do blocks=`cat $tmpFile`; rm -f $tmpFile
     blocks=`expr match "$blocks" "\([0-9]*\)"`
     [ -n "$nTapes" ] && { nTapes=`expr $nTapes - 1`;
                           [ "$nTapes" = 0 ] && return;
                         }
     # cpio sagt leider erst tschuess, wenn die pipe bricht, darum
     # hier eine Art Ende-Test. Das kann natuerlich trotzdem schief-
     # gehen, wenn die Menge der gesicherten Daten ein genaues Viel-
     # faches der Tape-Kapazitaet ist.
     # 
     if   [ "$blocks" != $nBlocks ] || [ "$blocks" = "0" ]
     then : # Band nicht ganz voll - kann nur letztes sein
          break;
     fi
     volNum=`expr $volNum + 1`
     if   [ -n "$isTerm" ]
     then echo $msg | sed s/%d/$volNum/ >/dev/tty
          read dummy </dev/tty
     else echo $msg | sed s/%d/$volNum/ | Notify
          result=$?
     fi
  done
  rm -f $tmpFile
  return 0
}

#
# PROCEDURE ReadTapeDir(dev:ARRAY OF CHAR; kbBlocks:CARDINAL;
#                       msg:ARRAY OF CHAR; nTapes: CARDINAL)
ReadTapeDir()
{ 
  DDDevIn $1 $2 "$3" | cpio -itcvB
}

#
# ------------------------------- MAIN ----------------------------------------
#

#
# ACHTUNG : die Uebernahme der Parameter muss _VOR_ dem ersten Aufruf von
# "MultiPrint", "Print" usw. passieren, da diese die Parameter $1, $2 usw.
# neu belegen !!!
#
if   [ -n "$1" ]
then DEVICE=$1
elif [ -c /dev/exa ]
then DEVICE=/dev/exa
elif [ -c /dev/rmt0 ]
then DEVICE=/dev/rmt0
elif [ -c /dev/optical ]
then DEVICE=/dev/optical
fi
export DEVICE
case $DEVICE in
     *exa*|*rmt*) isTape=1;;
               *) isTape=;;
esac
export isTape

if   [ -t 0 ]
then isTerm=1
else isTerm=
fi
export isTerm

[ -z "$BITSLIB" ] && BITSLIB=/bitslib
[ -z "$OS" ] && . $BITSLIB/bin/.ac-sh-funcs

if   [ -n "$isTerm" ] 
then if [ "$OS" = "SunOS" ] || [ "$OS" = "IRIX" ]
     then VERBOSE=V
     else VERBOSE=
     fi
else VERBOSE=v
fi

MSG_CAT=$BITSLIB/service/SERVImsg.${LANGUAGE}
. $BITSLIB/bin/.Messages

#echo "\nSicherung auf : $DEVICE / isTape='$isTape'\n"

GetMsg saveSystem selectedDevice
if   [ ! -c "$DEVICE" ]
then GetMsg saveSystem noSuchDevice
     echo ""
     exit 1
fi

#> ACHTUNG : Bitte bedenken Sie, dass die Anwenderplattenbereiche
#> (/projects und evt. /proj) bei dieser Sicherung nicht mit erfasst werden.
#> 
BlockPrint saveSystem startUpMsg

#--- setzt $nBlocks auf Anzahl der 5k-Blcke, die auf den Datentrger passen
ComputeNBlocks $DEVICE || exit 1
echo "Capacity : $nBlocks * 5k = `expr $nBlocks \* 5 / 1024`MB\n"
#nBlocks=`expr 20 \* 1024 \* 1024 / 5120`
#echo "Capacity : $nBlocks"
M=`GetMsg saveSystem nextTapeMsg`

if   WriteTape $DEVICE $nBlocks "$M"
then :
else : #> Fehler beim Schreiben !
       #> Bitte <ENTER> druecken und die Sicherung wiederholen
       BlockPrint saveSystem writeError
       [ -n "$isTerm" ] && read dummy
       exit 1
fi

#> `tput bel`
#> So, fertig.
#> Soll das Band zur Kontrolle nochmal ueberprueft werden ?
#> Dabei wird das Inhaltsverzeichnis auf dem Bildschirm angezeigt -
#> kann eine Weile dauern ? (j/n) 
BlockPrint saveSystem 14
#
# Loop, weil man beim Arbeiten mit Folgebaendern leicht mal vergessen
# kann, die Bandstation auf OnLine zu stellen.
#
saveErr=
while Yes
do  : #> Denken Sie daran, das erste Band einzulegen, wenn zur Sicherung
      #> mehrere Baender noetig waren !
      #> Betaetigen Sie <ENTER> zum Fortfahren...\c
      BlockNotify saveSystem verifyMsg
      if   [ -n "$isTape" ]
      then mtape fname $DEVICE rew #--- sicher ist sicher
      fi
      if   ReadTapeDir $DEVICE $nBlocks "$M"
      then echo "\007Okay."
           saveErr=
           break;
      else echo "\007"
	   #> Oha, da scheint wohl was nicht geklappt zu haben !
	   #> Noch ein Versuch ?
	   BlockPrint saveSystem 19
	   saveErr=1
      fi
done
if   [ -n "$saveErr" ]
then : #> Bitte <ENTER> druecken und die Sicherung wiederholen
     GetMsg saveSystem tryAgain
     [ -n "$isTerm" ] && read dummy
fi
