#!/bin/sh
#
# bootcd2disk
#
# DISK=auto, we will build an boot partition with size defined in BOOTS
  
TODOY="-y"
TODO="" mm=0
IAHEAD="bootcd2disk"
IMAGEURL=""
IMAGEURLCMD=""
SCRIPT=""
CONFDIR="/etc/bootcd"
ONLYMOUNT=""
ONLYUNMOUNT=""
CHROOTDIR=""
MNTBOOTCDDISC="mnt/bootcd.disc"
COPYDEST="/$MNTBOOTCDDISC"
IGNORE=""
STDOUT=""
ROOT=""
ORIGINALDISKNAME=""
ISOLOOPBACK=""
DEBUG=""

# function: usage
# get: $1 -- error string
usage()
{
  [ "$1" ] && echo  >&2 "$1"

  echo  >&2 " $(basename $0) copy a system running from bootcd to a disk."
  echo  >&2 " syntax:  -i           -- interactiv operation"
  echo  >&2 "          -d           -- turn debug on"
  echo  >&2 "          -s           -- be silent and no interaction"
  echo  >&2 "          -c <confdir> -- use another configuration directory"
  echo  >&2 "          -url <url>   -- url from imageserver"
  echo  >&2 "                          (overwrite IMAGEURL from config)"
  echo  >&2 "          -onlymount   -- only mount disks"
  echo  >&2 "          -onlyunmount -- only unmount disks"
  echo  >&2 "          -r <root>    -- debian root"
  echo  >&2 "          -o           -- use original disk names for only[un]mount"
  echo  >&2 "          -mkchroot <dir> -- bootcd will be copied to <dir>/chroot"
  echo  >&2 ""
  exit 1
}

domount()
{
  echo "--- mounting DISK ---" 
  dbg "COPYDEST=<$COPYDEST>"
  dbg "MOUNT=<$MOUNT>"
  mkdir -p $COPYDEST
  eval "$MOUNT"
}

dobind()
{
  echo "--- binding mounted DISK ---"
  dbg "COPYDEST=<$COPYDEST>"
  dbg "BIND=<$BIND>"
  eval "$BIND" 
}

todo_domount()
{
  # use global TODO mm ...

  if [ "$ROOT" -a "$BIND" ]; then
    # we are in chroot and BIND is defiled
    mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
    if [ "$SCRIPT" ]; then
      in_ignore $mm "^--- .* ---$"
    else
      in_stdout $mm "^--- .* ---$"
    fi
    TODO="$TODO \"dobind # binding all partitions to $COPYDEST\""

  else
    mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
    if [ "$SCRIPT" ]; then
      in_ignore $mm "^--- .* ---$"
    else
      in_stdout $mm "^--- .* ---$"
    fi
    TODO="$TODO \"domount # mount all partitions to $COPYDEST\""
  fi
}

dounmount()
{
  echo "--- unmounting DISK ---"
  dbg "UMOUNT=<$UMOUNT>"
  eval "$UMOUNT"
}

todo_dounmount()
{
  # use global TODO mm

  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  if [ "$SCRIPT" ]; then
    in_ignore $mm "^--- .* ---$"
  else
    in_stdout $mm "^--- .* ---$"
  fi

  TODO="$TODO \"dounmount\""
}

# get options
while [ "$1" ]; do
  case "$1" in
     "-h"|"--help")
        usage
        ;;
     "-i")
        TODOY=""
	shift
        ;;
   "-url")
        IMAGEURLCMD="$2"
        ISOLOOPBACK="/tmp/isoloopback"
        shift 2
        ;;
     "-d")
        DEBUG="$1"
	shift
        ;;
     "-c")
        CONFDIR="$2"
	[ "$CONFDIR" = "." ] && CONFDIR="$PWD"
        shift 2
        ;;
     "-s")
        SCRIPT="$1"
	shift
        ;;
     "-onlymount")
        ONLYMOUNT="$1"
        shift
        ;;
     "-onlyunmount")
	ONLYUNMOUNT="$1"
	shift
	;;
     "-o")
	ORIGINALDISKNAME="$1"
	shift
        ;;
     "-r")
        ROOT="$2"
        BOOTCDMP="$ROOT/$MNTBOOTCDDISC" # This may change mount and unmount commands in bootcd2disk.conf
        shift 2
        ;;
     "-mkchroot")
        CHROOTDIR="$2"
	COPYDEST="$CHROOTDIR/chroot"
	shift 2
	;;
        *)
        usage "ERROR: option \"$1\" unknown!"
        ;;
  esac
done

# Set variables that are not forced in bootcd2disk.conf for now
MD=""

# Read bootcd2disk.conf
CONFVARS="DISK0 SFDISK0 EXT2FS EXT3FS EXT4FS SWAP BIND MOUNT UMOUNT FSTAB LILO SSHHOSTKEY \
  UDEV_FIXNET IMAGEURL TRYFIRST GRUB GRUB2 LVMGRP LVMVOL \
  GRUBBOOTDISK GRUBDEVICEMAP GRUBBOOTDIR PARTITIONLABEL"
unset $CONFVARS
[ ! -f $ROOT/$CONFDIR/bootcd2disk.conf ] && err "No file $ROOT/$CONFDIR/bootcd2disk.conf"
. $ROOT/$CONFDIR/bootcd2disk.conf

# read bootcd-run.lib
# bootcd-run.lib must be read after bootcd2disk.conf because it needs ERRLOG
# bootcd-run.lib must be read before using its functions exp: err
if [ -f ./bootcd-run.lib ]; then
  echo "Using local ./bootcd-run.lib" >&2
  . ./bootcd-run.lib
elif [ -f $ROOT/usr/share/bootcd/bootcd-run.lib ]; then
  . $ROOT/usr/share/bootcd/bootcd-run.lib 
else
  echo "Error: Mandatory lib bootcd-run.lib not found! ABORT!"
  exit 1
fi

[ "$DEBUG" ] && dbgon

for i in $CONFVARS; do
  [ "`set | grep ^$i=`" ] || err "$i is not set in $ROOT/$CONFDIR/bootcd2disk.conf"
done

# Overwrite Config with Commandline
[ "$IMAGEURLCMD" ] && IMAGEURL="$IMAGEURLCMD"

# read bootcd2disk.lib
BOOTCD2DISKLIB=./bootcd2disk.lib
if [ -f $BOOTCD2DISKLIB ]; then
  [ "$SCRIPT" ] || echo "Using local $BOOTCD2DISKLIB" >&2
  . $BOOTCD2DISKLIB
else
  BOOTCD2DISKLIB=$ROOT/usr/share/bootcd/bootcd2disk.lib
  if [ -f $BOOTCD2DISKLIB ];then
    . $BOOTCD2DISKLIB
  else
    echo "Error: Mandatory lib $BOOTCD2DISKLIB not found! ABORT!"
    exit 1
  fi
fi

# useoriginaldisk - sets DISK0,DISK1,... to ORIG_DISK0,ORIG_DISK1,...
useoriginaldisk()
{
  if [ "$ORIGINALDISKNAME" ]; then
    for i in $DISKVARS; do
      eval "DISK$i=\$ORIG_DISK$i"
    done
  fi
}

getdiskvars # sets DISKVARS
check_auto # Has to be checked before setting DISKS
check_DISK0  # sets DISKS found on booted system
useoriginaldisk # with -o: sets DISK0,DISK1,... to ORIG_DISK0,ORIG_DISK1,...
check_SWAP_MD_MOUNT_UMOUNT_VFAT_OPT_FSTAB_PARTITIONLABEL

if [  "$ONLYMOUNT" ]; then
  todo_domount
  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
  exit $?
elif [  "$ONLYUNMOUNT" ]; then
  todo_dounmount
  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
  exit $?
fi

# run functions from bootcd2disk.lib
read_thisboot
check_kern
check_SFDISK0
check_EXT
check_GRUB2_GRUB_LILO
check_OPT_LVM

DO_BEFORE_COPY=$(egrep "^[[:space:]]*(function)*[[:space:]]*before_copy" $ROOT/$CONFDIR/bootcd2disk.conf)
DO_AFTER_COPY=$(egrep "^[[:space:]]*(function)*[[:space:]]*after_copy" $ROOT/$CONFDIR/bootcd2disk.conf)

# getdata - print without empty lines and comments
getdata()
{
  echo "$*" | sed "s/#.*$//" | grep -v "^$"
}

### Main ###

A=""
while [ "$A" != "y" -a "$A" != "n" -a "$SCRIPT" = "" ]
do
  if [ "$CHROOTDIR" ]; then
    echo "Directory $CHROOTDIR will be deleted and created again! " | tee -a $ERRLOG >&2
    [ "$DO_BEFORE_COPY" ] && echo "do_before_copy is defined." | tee -a $ERRLOG >&2
    [ "$DO_AFTER_COPY" ] && echo "do_after_copy is defined." | tee -a $ERRLOG >&2
    [ "$RESTORECMD" ] && echo "RESTORECMD is defined." | tee -a $ERRLOG >&2
  else
    for i in $DISKVARS; do
      echo "Harddisk $i ($(eval "echo \"\$DISK$i\"")) will be erased!!!" |
        tee -a $ERRLOG >&2
    done
    [ "$SWAP" ] && echo "Partition $SWAP will be newly created as SWAP !!!" | tee -a $ERRLOG >&2
    [ "$EXT2FS" ] && echo "Partition $EXT2FS will be newly created as ext2 !!!" | tee -a $ERRLOG >&2
    [ "$EXT3FS" ] && echo "Partition $EXT3FS will be newly created as ext3 !!!" | tee -a $ERRLOG >&2
    [ "$EXT4FS" ] && echo "Partition $EXT4FS will be newly created as ext4 !!!" | tee -a $ERRLOG >&2
    [ "$VFAT" ] && echo "Partition $VFAT will be newly created as vfat !!!" | tee -a $ERRLOG >&2
  fi
  echo "(y/n) " | tee -a $ERRLOG >&2
  if [ "$SCRIPT" ]; then
    A="y"
  else
    read A
    # Next line handles EOF from a pipe as (e)xit
    [ $? -ne 0 ] && A="n"
  fi
  echo "$A" >> $ERRLOG
done
if [ "$A" = "n" ]; then
  exit 1
fi

trap cleanup 2

# zerodsk <dev1> [<dev2> ...]
zerodsk()
{
  local DELPV
  local dsk
  DELPV="$@"

  echo "--- Destroy old disk infos $DELPV ---"
  for dsk in $DELPV; do
    dd if=/dev/zero of=$dsk bs=1k count=1 conv=notrunc
  done
}

lvmreset()
{
  local IAHEAD="$IAHEAD/lvmreset"
  local TODO="" mm=0

  if [ "$LVMGRP" -a "$LVMVOL" ]; then

    # delete all pvdisplay | grep "PV Name"
    ALLPV="$(pvdisplay -c 2>/dev/null | 
      sed -n "s|[[:blank:]]*\(/dev/[^:]*\):.*|\1|p")"

    echo "All physical Volumes ALLPV=<$ALLPV>" >>$ERRLOG

    for i in $DISKVARS; do
      # Search for old Partitions on reused disks
      DELPV="$(echo "$ALLPV" | grep "^$(eval "echo \"\$DISK$i\"")")"
      # All on one line
      DELPV="$(echo $DELPV|awk '{printf("%s ",$0)}')"

      if [ "$(echo "$DELPV" | grep "[[:alnum:]]")" ]; then
        # Try to use pvremove first (ignore anything, only write to log)
        mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
        in_ignore $mm ".*"
        TODO="$TODO \"pvremove -ff -y $DELPV\""
      fi

      # Add the disk itself
      DELPV="$DELPV $(eval "echo \"\$DISK$i\"")"

      mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
      in_stdout $mm "^--- .* ---$"
      in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records in$"
      in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records out$"
      in_ignore $mm "^[[:digit:]]\+ bytes\>.*\<copied\>"
      TODO="$TODO \"zerodsk $DELPV\""
    done
  fi
  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$LVMGRP" -a "$LVMVOL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"lvmreset # deactivate lvm, delete lvm info on disk\""
fi

unreadable()
{
  local unreadable=""
  local err
  for i in $DISKVARS; do
    d=$(eval "echo \"\$DISK$i\"")
    # Sometimes it just takes longer
    for j in 1 2 3 4 5 6 7; do
      err="$(sfdisk -R $d 2>&1)"
      if [ "$(echo "$err" | grep "Device or resource busy")" ]; then
        if [ $j -eq 7 ]; then
          echo "$d was not readable ($j); giving up" >&2
          unreadable="=== begin output of \"sfdisk -R $d\" ===
$err
=== end output of \"sfdisk -R $d\" ==="
          break 2
        else
          sleep 1
          echo "$d was not readable ($j); retrying" >&2
        fi
      else
        if [ $j -ne 1 ]; then
          echo "$d is now readable ($j); ok" >&2
        fi
        break
      fi
    done
  done
  echo "$unreadable"
}

zerodisk_if_unreadable()
{
  local IAHEAD="$IAHEAD/lvmreset"
  local TODO="" mm=0
  local DELPV=""

  if [ "$(unreadable)" ]; then
    for i in $DISKVARS; do
      DELPV="$(eval "echo \"\$DISK$i\"")"
      mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
      in_stdout $mm "^--- .* ---$"
      in_ignore $mm "1+0 records in"
      in_ignore $mm "1+0 records out"
      in_ignore $mm "1024 bytes.*copied.*"
      TODO="$TODO \"zerodsk $DELPV\""
    done
    eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
  fi
}
if [ ! "$CHROOTDIR" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO \"zerodisk_if_unreadable\""
fi

ask_for_reboot()
{
  local err
  err="$(unreadable)"
  if [ "$err" ]; then
    echo "$err"
    echo "Rereading the partition says \"Device or resource busy\""
    echo "The partition tabel is now deleted."
    echo "After reboot bootcd2disk should work!"
    echo " ------------------------ "
    echo "( Press RETURN to reboot )"
    echo " ------------------------ "
    read dummy
    reboot 
    exit
  fi
}
if [ ! "$CHROOTDIR" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO \"ask_for_reboot # (if neccessary)\""
fi

partdisk()
{
  local d s o i

  for i in $DISKVARS; do
    d=$(eval "echo \"\$DISK$i\"")
    s=$(eval "echo \"\$SFDISK$i\"")
    o=$(eval "echo \"\$SFDISKOPTS$i\"")
    echo "--- Partitioning DISK$i ($d) ---"
    echo "$s" | sfdisk $o --force -qL -uM $d >/dev/null
  done
  # Maybe we have to Reboot now, because of
  #   BLKRRPART: Device or resource busy
  #   The command to re-read the partition table failed
  #   Reboot your system now, before using mkfs
  # so first do a sync
  sync
}
if [ ! "$CHROOTDIR" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_ignore $mm "unrecognized partition table type"
  in_ignore $mm "^sfdisk: ERROR: sector .* does not have an msdos signature"
  in_ignore $mm "^No partitions found"
  in_ignore $mm "^$"
  in_stdout $mm ".*"
  TODO="$TODO \"partdisk # partition disks $(for i in $DISKVARS; do echo -n "$(eval "echo \"\$DISK$i\"") "; done; echo "")\""
fi

# wait until new device files from sfdisk are available
if [ -x /sbin/udevadm ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  TODO="$TODO \"/sbin/udevadm settle\""
fi

# We have systems even at this point where reboot was needed
# But this should be rarely needed
ask_for_reboot2()
{
  local err
  err="$(unreadable)"
  if [ "$err" ]; then
    echo "$err"
    echo "Rereading the partition after partitioning says \"Device or resource busy\""
    echo "The partition tabel is now created as needed."
    echo "After reboot bootcd2disk should work!"
    echo " ------------------------ "
    echo "( Press RETURN to reboot )"
    echo " ------------------------ "
    read dummy
    reboot 
    exit
  fi
}
if [ ! "$CHROOTDIR" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO \"ask_for_reboot2 # (if neccessary)\""
fi

mddisk()
{
  local IAHEAD="$IAHEAD/mddisk"
  local TODO="" mm=0

  echo "--- mddisk ---" | tee -a $ERRLOG >&2

  # while ... gives a subshell, to set vars we have to eval the set commands
  eval "$(
    getdata "$MD" |
    while read mddev level dsks; do
      dsks="$(echo "$dsks" |sed "s/mdadm.*//")"
          cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_stdout $mm "^--- .* ---$"
in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records in$"
in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records out$"
in_ignore $mm "^[[:digit:]]\+ bytes\>.*\<copied\>"
END
      echo "TODO=\"\$TODO \\\"zerodsk $dsks\\\"\""
    done
    getdata "$MD" |
    while read mddev level dsks; do
      cmd="$(echo "$dsks"|sed -n "s/.*\(mdadm.*\)/\1/p")"
      dsks="$(echo "$dsks" |sed "s/mdadm.*//")"
      nr="$(echo "$dsks"|wc -w)"
        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "mdadm: array .* started"
in_ignore $mm "^mdadm: .* appears to contain an ext2fs file system"
in_ignore $mm "^[[:space:]]\+ size="
in_ignore $mm "^mdadm: .* appears to be part of a raid array"
in_ignore $mm "^[[:space:]]\+ level="
in_ignore $mm "^Continue creating array?"
END
      if [ "$cmd" ]; then
        echo "TODO=\"\$TODO \\\"$cmd\\\"\""
      else
        echo "TODO=\"\$TODO \\\"echo y | mdadm --create $mddev --level=$level --raid-devices=$nr --quiet --force $dsks\\\"\""
      fi
    done
  )"

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$MD" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"mddisk\""
fi

lvm_pvcreate()
{
  local IAHEAD="$IAHEAD/lvm_pvcreate"
  local TODO="" mm=0

  echo "--- pvcreate ---" | tee -a $ERRLOG >&2

  # while ... gives a subshell, to set vars we have to eval the set commands
  eval "$(
    getdata "$LVMGRP" | sed "s/vgcreate.*//" |
    while read grp dsks; do
      for dsk in $dsks; do

        # After Disk Partitioning, there could be new places with old
        # LVM Info, so we delete it with pvremove and dd before running pvcreate
        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm ".*"
END
        echo "TODO=\"\$TODO \\\"pvremove -ff -y $dsk\\\"\""
        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "WARNING: Forcing physical volume creation on .* of volume group \".*\""
in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records in$"
in_ignore $mm "^[[:digit:]]\++[[:digit:]]\+ records out$"
in_ignore $mm "^[[:digit:]]\+ bytes\>.*\<copied\>"
END
        echo "TODO=\"\$TODO \\\"dd if=/dev/zero of=$dsk bs=1k count=1 conv=notrunc\\\"\""

        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "WARNING: Forcing physical volume creation on .* of volume group \".*\""
in_ignore $mm "Physical volume \".*\" successfully created"
in_ignore $mm "Writing physical volume data to disk \".*\""
END
        echo "TODO=\"\$TODO \\\"pvcreate --quiet -d -ff -y $dsk\\\"\""

      done
    done
  )"

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$LVMGRP" -a "$LVMVOL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"lvm_pvcreate\""
fi


lvm_vgcreate()
{
  local IAHEAD="$IAHEAD/lvm_vgcreate"
  local TODO="" mm=0

  echo "--- vgcreate ---" | tee -a $ERRLOG >&2

  # while ... gives a subshell, to set vars we have to eval the set commands
  eval "$(
    getdata "$LVMGRP" |
    while read grp dsks; do
      cmd="$(echo "$dsks"|sed "s/.*\(vgcreate.*\)/\1/"|grep vgcreate)"
        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "Volume group \".*\" successfully created"
END
      if [ "$cmd" ]; then
        echo "TODO=\"\$TODO \\\"$cmd\\\"\""
      else
        echo "TODO=\"\$TODO \\\"vgcreate --quiet $grp $dsks\\\"\""
      fi
        cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "0 logical volume(s) in volume group \".*\" now active"
END
      echo "TODO=\"\$TODO \\\"vgchange --quiet -aey $grp\\\"\""
    done
  )"

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$LVMGRP" -a "$LVMVOL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"lvm_vgcreate\""
fi

lvm_lvcreate()
{
  local IAHEAD="$IAHEAD/lvm_lvcreate"
  local TODO="" mm=0

  echo "--- lvcreate ---" | tee -a $ERRLOG >&2

  # while ... gives a subshell, to set vars we have to eval the set commands
  eval "$(
    getdata "$LVMVOL" |
    while read vol s grp cmd; do
      cat <<'END'
mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
in_ignore $mm "Logical volume \".*\" created"
in_ignore $mm "/dev/cdrom: open failed: Read-only file system$"
in_stdout $mm "Rounding up size to full physical extent"
END
      if [ "$cmd" ]; then
        echo "TODO=\"\$TODO \\\"$cmd\\\"\""
      else
        echo "TODO=\"\$TODO \\\"lvcreate -n $vol -L $s $grp\\\"\""
      fi
    done
  )"

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$LVMGRP" -a "$LVMVOL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"lvm_lvcreate\""
fi

lvm_vgchange()
{
  local IAHEAD="$IAHEAD/lvm_vgchange"
  local TODO="" mm=0

  echo "--- Activate LVM ---" | tee -a $ERRLOG >&2

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_ignore $mm "Reading all physical volumes.  This may take a while..."
  in_ignore $mm "Found volume group \".*\" using metadata type lvm2"
  in_ignore $mm "/dev/cdrom: open failed: Read-only file system"
  in_ignore $mm "Attempt to close device '/dev/cdrom' which is not open."
  TODO="$TODO \"vgscan --quiet\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_ignore $mm "[1-9][0-9]* logical volume(s) in volume group \".*\" now active"
  TODO="$TODO \"vgchange --quiet -ay\""

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$LVMGRP" -a "$LVMVOL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"lvm_vgchange\""
fi

vfat()
{
  local IAHEAD="$IAHEAD/vfat"
  local TODO="" mm=0

  for i in $VFAT; do
    echo "--- Building Filesystem $i with mkdosfs ---" | tee -a $ERRLOG >&2

    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^mkdosfs "
    TODO="$TODO \"mkdosfs $i\""
  done

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$VFAT" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"vfat # mkdosfs $VFAT\""
fi


extfs()
{
  local IAHEAD="$IAHEAD/extfs"
  local TODO="" mm=0 l=""

  for i in $EXT2FS; do
    l="$(echo "$PARTITIONLABEL" | grep "^$i:" | sed "s|.*:||")"
    [ "$l" ] && l="-L $l"
    echo "--- Building Filesystem $i with mke2fs -t ext2 $l ---" | tee -a $ERRLOG >&2
    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^mke2fs "
    TODO="$TODO \"mke2fs -t ext2 $l -q $i\""
  done

  for i in $EXT3FS; do
    l="$(echo "$PARTITIONLABEL" | grep "^$i:" | sed "s|.*:||")"
    [ "$l" ] && l="-L $l"
    echo "--- Building Filesystem $i with mke2fs -t ext3 -j $l ---" | tee -a $ERRLOG >&2
    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^mke2fs "
    TODO="$TODO \"mke2fs -t ext3 -j $l -q $i\""
  done

  for i in $EXT4FS; do
    l="$(echo "$PARTITIONLABEL" | grep "^$i:" | sed "s|.*:||")"
    [ "$l" ] && l="-L $l"
    echo "--- Building Filesystem $i with mke2fs -t ext4 $l ---" | tee -a $ERRLOG >&2
    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^mke2fs "
    TODO="$TODO \"mke2fs -t ext4 $l -q $i\""
  done

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "${EXT2FS}${EXT3FS}${EXT4FS}" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"extfs # mke2fs ${EXT2FS}${EXT3FS}${EXT4FS}\""
fi

if [ ! "$CHROOTDIR" ]; then
  todo_domount
fi

if [ "$CHROOTDIR" -a "$CHROOTDIR" != "/" -a "$CHROOTDIR" != "." ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  TODO="$TODO \"rm -rf $CHROOTDIR\""

  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  TODO="$TODO \"mkdir -p $COPYDEST\""
fi

# remove all interfaces from udev persistent rules file
# needed if you install on other machines
udev_fixnet()
{
  local f
  for f in \
    /etc/udev/rules.d/z25_persistent-net.rules \
    /etc/udev/rules.d/70-persistent-net.rules
  do
    # if we can find the rules file, and change it sucessfull, we leave
    # the loop with break and exit this function with return 0, else return 1
    [ -e "$f" ] && sed -i "s/^\([^#]\+.*\)/#\1 # disabled by bootcd2disk/" $f && break
  done
  return 0
}

if [ "$UDEV_FIXNET" = "yes" ]; then 
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  TODO="$TODO udev_fixnet"
fi

# use image from a image server and copy it to the later swap-partion
# the partition must be large enough to hold the whole disk image
copyfromserver_before()
{
  # timeout for dns-query and connection timeout (seconds)
  local timeout=30
  local IAHEAD="$IAHEAD/copyfromserver_before"
  local TODO="" mm=0
  local url

  echo "--- copying image from image server ---" | tee -a $ERRLOG >&2
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_stdout $mm "^mke2fs "
  TODO="$TODO \"mke2fs -q $SWAP\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"mkdir -p /tmp/swapfs\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"mount $SWAP /tmp/swapfs\""

  if [ "$(echo "$IMAGEURL" | grep "^file://")" ]; then
    url="$(echo "$IMAGEURL" | sed "s|^file://\(.*\)$|\1|")"
    if [ -b "$url" ]; then
      mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
      in_stdout $mm "records in$"
      in_stdout $mm "records out$"
      in_stdout $mm "bytes .* copied"
      TODO="$TODO \"dd if=$url of=/tmp/swapfs/cdimage.iso\""
    elif [ -f "$url" ]; then
        mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
        TODO="$TODO \"cp $url /tmp/swapfs/cdimage.iso\""
    else
      echo "No file <$url>" | tee -a $ERRLOG >&2
      exit 3
    fi
  else
    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^--[[:digit:]:]*--.*"
    in_stdout $mm "^[[:space:]]*=> .*"
    in_stdout $mm "^Resolving .*"
    in_stdout $mm "^Connecting .*"
    in_stdout $mm "^Logging .*"
    in_stdout $mm "^==> SYST .*"
    in_stdout $mm "^==> TYPE .*"
    in_stdout $mm "^==> PASV .*"
    in_stdout $mm "^Length: .*"
    in_stdout $mm "^[[:space:]]*OK.*"
    in_stdout $mm "^Length .*"
    in_stdout $mm "^$"
    in_stdout $mm "^[[:digit:]:]* .*"
    in_stdout $mm "^[[:space:]]*[[:digit:]:K]* .*"
    in_stdout $mm "^HTTP request sent, .* 200 OK[[:space:]]*$"
    in_stdout $mm "^==> SIZE "
    in_stdout $mm "^Saving to: ./tmp/swapfs/cdimage.iso.*"
    in_stdout $mm "^.*/tmp/swapfs/cdimage.iso. saved.*"
    in_stdout $mm "^--....-..-.. ..:..:..--  $IMAGEURL$"
    TODO="$TODO \"wget --no-check-certificate --dns-timeout=$timeout --connect-timeout=$timeout -O /tmp/swapfs/cdimage.iso $IMAGEURL\""
  fi

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"mkdir -p $ISOLOOPBACK\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_stdout $mm "^mount: warning: /tmp/isoloopback seems to be mounted read-only\.$"
  TODO="$TODO \"mount -o loop /tmp/swapfs/cdimage.iso $ISOLOOPBACK\""

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ "$IMAGEURL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO copyfromserver_before"
fi

do_before_copy()
{
  echo "--- do function before_copy ---" | tee -a $ERRLOG >&2
  before_copy
}
# only call the function, if it is defined
if [ "$DO_BEFORE_COPY" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO \"do_before_copy # run function before_copy defined in bootcd2disk.conf\""
fi

handling_udev()
{
  local IAHEAD="$IAHEAD/handling_udev"
  local TODO="" mm=0

  echo "--- handling udev ---" 
  # -- udev --
  # The filesystem has static device files in /dev.
  # But tmpfs is mounted over /dev and hides the static device files.
  # The static device files are mounted again in /dev/.static/dev/.
  # This means bootcd has only to copy /dev/.static/dev.
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"cp -a -x /ram1/dev/.static/dev $COPYDEST\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"mkdir -p $COPYDEST/dev/.static\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"chown root:root $COPYDEST/dev/.static\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"chmod 700 $COPYDEST/dev/.static\""

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}

copycdram()
{
  local IAHEAD="$IAHEAD/copycdram"
  local TODO="" mm=0

  echo "--- copying CD and RAM to $COPYDEST ---" | tee -a $ERRLOG >&2

  # Normally $ISOLOOPBACK is / but it could be changed by the functions
  # copyfromserver_before() or before_copy
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"cd /$ISOLOOPBACK; find . -mount | cpio --quiet -pdum $COPYDEST\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"rm -rf $COPYDEST/rr_moved/ $COPYDEST/isolinux/\""

  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"rm $COPYDEST/usr/bin/bootcd2disk \
    $COPYDEST/usr/bin/bootcdflopcp \
    $COPYDEST/etc/bootcd/bootcd2disk.conf \
    $COPYDEST/etc/bootcd/thisbootcd.conf\""

  # restore /etc/securetty
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"cat $COPYDEST/etc/securetty | awk 'BEGIN {cut=0} /added by bootcdwrite BEGIN/ { cut=1 } {if (cut==0) {print}} /added by bootcdwrite END/ {cut=0}' >$COPYDEST/etc/securetty.tmp; mv $COPYDEST/etc/securetty.tmp $COPYDEST/etc/securetty\""

  # files that do not always exist
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"rm -f $COPYDEST/usr/bin/bootcdmk2diskconf\""

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ ! "$RESTORECMD" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"copycdram # copy cd and ram to $COPYDEST, delete unneeded stuff\""
fi

if [ "$RESTORECMD" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_stdout $mm "^star: [[:digit:]]\+ blocks + [[:digit:]]\+ bytes (total of [[:digit:]]\+ bytes = .*)\."
  TODO="$TODO \"$RESTORECMD\""
fi

# configure the swap-partition back to swap
give_swappartition_free()
{
  # timeout for dns-query and connection timeout (seconds)
  local timeout=30
  local IAHEAD="$IAHEAD/give_swappartition_free"
  local TODO="" mm=0

  echo "--- copying image from image server ---" | tee -a $ERRLOG >&2

  # cleanup again
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_ignore $mm "loop: can.t delete device /dev/loop0"
  TODO="$TODO \"umount -d $ISOLOOPBACK\""

  # free loopdevice
#  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
#  TODO="$TODO \"losetup -d /dev/loop0\""

  # cleanup again
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  TODO="$TODO \"umount /tmp/swapfs\""

  # rebuild swap
  mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
  in_norun $mm  
  TODO="$TODO \"swap\""

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ "$IMAGEURL" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO give_swappartition_free"
fi

swap()
{
  local IAHEAD="$IAHEAD/swap"
  local TODO="" mm=0 l=""

  for i in $SWAP; do
    l="$(echo "$PARTITIONLABEL" | grep "^$i:" | sed "s|.*:||")"
    [ "$l" ] && l="-L $l"
    echo "--- making SWAP $i with mkswap $l ---" | tee -a $ERRLOG >&2
    mm=$(($mm+1)); eval local IGNORE${mm}=\"\"; eval local STDOUT${mm}=\"\"
    in_stdout $mm "^Setting up swapspace"
    in_stdout $mm "^no label, "
    in_stdout $mm "^LABEL="
    # we need option -f for mkswap on logical volumes, to prevent the warning
    #    mkswap: /dev/mapper/vg_rh6-lv_swap: warning: 
    #            don't erase bootbits sectors
    #            on whole disk. Use -f to force.
    TODO="$TODO \"mkswap -f $l $i\""
  done

  eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"
}
if [ \( ! "$CHROOTDIR" \) -a "$SWAP" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm 
  TODO="$TODO \"swap # mkswap $SWAP\""
fi

# The next function is usefull if we run in interactive
# mode and want to run chroot for some reason on another tty
mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_norun $mm
TODO="$TODO \"prepare_chroot $COPYDEST <-i>\""

do_after_copy()
{
  echo "--- do function after_copy ---"
  after_copy
}
# only call the function, if it is defined
if [ ! -z "$DO_AFTER_COPY" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_norun $mm
  TODO="$TODO \"do_after_copy # run function after_copy defined in bootcd2disk.conf\""
fi

do_fstab()
{
  if [ "$FSTAB" = "unchanged" ]; then
    echo "--- Will let fstab unchanged ---"
  else
    echo "--- Building fstab ---"
    FSTAB="$(real2uuid "$FSTAB")"
    dbg FSTAB="<$FSTAB>"
    echo "$FSTAB" > $COPYDEST/etc/fstab
  fi
}
mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_stdout $mm "^--- .* ---$"
TODO="$TODO \"do_fstab # create $COPYDEST/etc/fstab\""

bootloadercfg()
{
  local IAHEAD="$IAHEAD/bootloadercfg"
  local TODO="" mm=0


  if [ "$GRUB2" = "unchanged" ]; then
    dbg GRUB2="<$GRUB2>"
    echo "--- Will let grub/grub.cfg unchanged ---" | tee -a $ERRLOG >&2
  #elif [ "$GRUB2" = "auto" ]; then
  #  mkdir -p $COPYDEST/boot/grub
  #  grub-mkconfig | sed "s|/boot/|/|g" > $COPYDEST/boot/grub/grub.cfg
  #  I do not know how tu use grub-mkconfig. It seems not to support
  #  a separate /boot partition
  elif [ "$GRUB2" ]; then
    GRUB2="$(real2uuid "$GRUB2")"
    dbg GRUB2="<$GRUB2>"
    echo "--- Building grub/grub.cfg ---" | tee -a $ERRLOG >&2
    mkdir -p $COPYDEST/boot/grub
    echo "$GRUB2" > $COPYDEST/boot/grub/grub.cfg
  fi

  if [ "$GRUB" = "unchanged" ]; then
    dbg GRUB="<$GRUB>"
    echo "--- Will let grub/menu.lst unchanged ---" | tee -a $ERRLOG >&2
  elif [ "$GRUB" ]; then
    GRUB="$(real2uuid "$GRUB")"
    dbg GRUB="<$GRUB>"
    echo "--- Building grub/menu.lst ---" | tee -a $ERRLOG >&2
    mkdir -p $COPYDEST/boot/grub
    echo "$GRUB" > $COPYDEST/boot/grub/menu.lst
  fi

  if [ "$LILO" = "unchanged" ]; then
    echo "--- Will let lilo.conf unchanged ---" | tee -a $ERRLOG >&2
  elif [ "$LILO" ]; then
    echo "--- Building lilo.conf ---" | tee -a $ERRLOG >&2
    echo "$LILO" > $COPYDEST/etc/lilo.conf
  fi
}
mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_stdout $mm "^--- .* ---$"
in_stdout $mm "^Generating grub.cfg"
in_stdout $mm "^Found linux image"
in_stdout $mm "^Found initrd image"
in_stdout $mm "^done$"
TODO="$TODO bootloadercfg"

createsshkeys()
{
  if [ "$SSHHOSTKEY" = "unchanged" ]; then
    echo "--- Will let ssh keys unchanged ---" | tee -a $ERRLOG >&2
  elif [ "$SSHHOSTKEY" = "yes" ]; then
    # each installed PC gets a unique hostkey (only if hostkey already existed)
    TODO="$TODO \"create_host_keys $COPYDEST/etc/ssh\""
  elif [ "$SSHHOSTKEY" != "no" ]; then
    echo 'SSHHOSTKEY is not defined as "yes" or "no".' \
         'It will be treated as "no".'
  fi
}
mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_stdout $mm "^--- .* ---$"
TODO="$TODO createsshkeys"

enablecron()
{
  echo "--- Enabling turned off stuff ---" | tee -a $ERRLOG >&2
  for f in $DISABLE_CRON; do
    if [ -f $COPYDEST/$f.no_run_on_bootcd ]; then 
      rm $COPYDEST/$f
      mv $COPYDEST/$f.no_run_on_bootcd $COPYDEST/$f
    fi
  done
}
if [ ! "$RESTORECMD" ]; then
  if [ "$DISABLE_CRON" ]; then
    mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
    in_stdout $mm "^--- .* ---$"
    TODO="$TODO enablecron"
  fi
fi

dogrub2()
{
  [ -z "$GRUBBOOTDIR" ] && GRUBBOOTDIR=0
  [ -z "$GRUBBOOTDISK" ] && GRUBBOOTDISK="hd0"

  if [ "$GRUBDEVICEMAP" = "auto" -o "$GRUBDEVICEMAP" = "" ]; then
    # Automatic handling.
    rm -f $COPYDEST/boot/grub/device.map
    grub-mkdevicemap -m $COPYDEST/boot/grub/device.map
  elif [ "$GRUBDEVICEMAP" = "no" ]; then
    # Do nothing.
    # We do not change device.map
    # This should work if a bootcd is installed on the original hardware
    :
  elif [ "$GRUBDEVICEMAP" ]; then
    # We explicit set a value to device.map
    # This is needed if nothing else helps
    echo "$GRUBDEVICEMAP" > $COPYDEST/boot/grub/device.map
  fi

  #grub-install --root-directory=$COPYDEST --force --no-floppy "($GRUBBOOTDISK)"
  chroot $COPYDEST grub-install --force --no-floppy "($GRUBBOOTDISK)"
}
if [ \( ! "$CHROOTDIR" \) -a "$GRUB2" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  # To much text
  in_stdout $mm ".*"
  TODO="$TODO \"dogrub2 # ($GRUBBOOTDISK)\""
fi

dogrub1_chroot()
{
  echo "--- Running grub1 chroot ---" | tee -a $ERRLOG >&2
  [ -z "$GRUBBOOTDIR" ] && GRUBBOOTDIR=0
  [ -z "$GRUBBOOTDISK" ] && GRUBBOOTDISK="hd0"

  if [ "$GRUBDEVICEMAP" = "auto" -o "$GRUBDEVICEMAP" = "" ]; then
    # Automatic handling.
    rm -f $COPYDEST/boot/grub/device.map
    # grub-mkdevicemap does not work always
    # grub-mkdevicemap -m $COPYDEST/boot/grub/device.map 
  elif [ "$GRUBDEVICEMAP" = "no" ]; then
    # Do nothing.
    # We do not change device.map
    # This should work if a bootcd is installed on the original hardware
    :
  elif [ "$GRUBDEVICEMAP" ]; then
    # We explicit set a value to device.map
    # This is needed if nothing else helps
    echo "$GRUBDEVICEMAP" > $COPYDEST/boot/grub/device.map
  fi

  chroot $COPYDEST grub-install --no-floppy "($GRUBBOOTDISK)"
}

prepare_grub_stage_files()
{
  echo "--- Preparing grub stage files ---" | tee -a $ERRLOG >&2
  # We need the corresponding grub files of the running kernel
  # This files should already be installed, but may not work with the 
  # bootcd kernel when restoring a system backed up with bootcdbackupwizard.
  # On a restored system the original files can normally be installed again,
  # with grub-install.
# if [ ! -d $COPYDEST/boot/grub.tmp ]; then
#   mkdir $COPYDEST/boot/grub.tmp
#   mv $COPYDEST/boot/grub/stage1 $COPYDEST/boot/grub/stage2 \
#      $COPYDEST/boot/grub/*stage1_5 $COPYDEST/boot/grub.tmp

    cp /usr/lib/grub/*/stage1 /usr/lib/grub/*/stage2 \
       /usr/lib/grub/*/*stage1_5 $COPYDEST/boot/grub/
# fi
}

dogrub1_manual()
{
  [ -z "$GRUBBOOTDIR" ] && GRUBBOOTDIR=0
  [ -z "$GRUBBOOTDISK" ] && GRUBBOOTDISK="hd0"


  # grub-install (the next 12 commandlines) is no longer used.
  #
  # Most of the time the command did not return 0 and so grub was used directly
  # anyway.
  # But now I got bug reports, that grub-install did not work, but returned 0. 
  # This resulted in an unbootable installation, because in this case grub was 
  # not used directy.
  #
  #echo "--- Running grub-install ---" | tee -a $ERRLOG >&2
  #grub-install --no-floppy --root-directory=$COPYDEST $GRUBBOOTDISK
  #
  #if [ $? -eq 0 ]; then
  #  return 0
  #fi
  #echo "--- grub-install did not work trying option --recheck ---"| tee -a $ERRLOG >&2
  #grub-install --recheck --no-floppy --root-directory=$COPYDEST $GRUBBOOTDISK
  #
  #if [ $? -eq 0 ]; then
  #  return 0
  #fi

  if [ "$GRUBDEVICEMAP" = "auto" -o "$GRUBDEVICEMAP" = "" ]; then
    # Automatic handling.
    # We delete device.map. So it will then be auto-created by grub.
    # This should work on different target hardware
    rm -f $COPYDEST/boot/grub/device.map
  elif [ "$GRUBDEVICEMAP" = "no" ]; then
    # Do nothing.
    # We do not change device.map
    # This should work if a bootcd is installed on the original hardware
    :
  elif [ "$GRUBDEVICEMAP" ]; then
    # We explicit set a value to device.map
    # This is needed if nothing else helps
    echo "$GRUBDEVICEMAP" > $COPYDEST/boot/grub/device.map
  fi

  echo "--- Running grub1 manual ---" | tee -a $ERRLOG >&2
  (
    for i in $GRUBBOOTDISK; do
      echo "root ($i,$GRUBBOOTDIR)
setup ($i)"
    done
    echo "quit"
  ) | grub --no-floppy --batch --device-map=$COPYDEST/boot/grub/device.map
}

# Do not restore grub_stage_files.
# Grub needs this files to boot. This Problem may not be seen
# immediately, because the files may be on disk for a long time.
# The "restore" will be done when grub-install runs on the 
# new system, with files from /usr/lib/grub/...
#restore_grub_stage_files()
#{
#  rm $COPYDEST/boot/grub/stage1 $COPYDEST/boot/grub/stage2 \
#     $COPYDEST/boot/grub/*stage1_5
#  mv $COPYDEST/boot/grub.tmp/* $COPYDEST/boot/grub
#  rmdir $COPYDEST/boot/grub.tmp
#}
#if [ \( ! "$CHROOTDIR" \) -a "$GRUB" ]; then
#  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
#  # To many text
#  in_stdout $mm ".*"
#  TODO="$TODO \"restore_grub_stage_files\""
#fi

dogrub1()
{
  dogrub1_chroot
  g1_cr_err=$?

  if [ $g1_cr_err -ne 0 ]; then
    echo "--- Retry manual ---" | tee -a $ERRLOG >&2
    prepare_grub_stage_files
    dogrub1_manual
  fi
}
if [ \( ! "$CHROOTDIR" \) -a "$GRUB" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  # To many text
  in_stdout $mm ".*"
  TODO="$TODO \"dogrub1 # root ($GRUBBOOTDISK,$GRUBBOOTDIR)\""
fi

dolilo()
{
  echo "--- Running lilo ---" | tee -a $ERRLOG >&2
  chroot $COPYDEST lilo -w
}
if [ \( ! "$CHROOTDIR" \) -a "$LILO" ]; then
  mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
  in_stdout $mm "^Added "
  in_stdout $mm "^--- .* ---$"
  TODO="$TODO dolilo"
fi

check_selinux()
{
  if [ -f $COPYDEST/etc/selinux/config ]; then
    dbg "found $COPYDEST/etc/selinux/config"
    if [ "$(grep "^SELINUX=enforcing[[:space:]]*$" $COPYDEST/etc/selinux/config)" ]; then
      sed -i "s/^SELINUX=enforcing[[:space:]]*$/SELINUX=permissive/" $COPYDEST/etc/selinux/config
      echo "SELINUX set from enforcing to permissive"
      echo "(please turn back after first boot in /etc/selinux/config)"
    fi
  else
    dbg "no file $COPYDEST/etc/selinux/config"
  fi
}
mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_stdout $mm "^DEBUG "
TODO="$TODO check_selinux" 

mm=$(($mm+1)); eval IGNORE${mm}=\"\"; eval STDOUT${mm}=\"\"
in_norun $mm
TODO="$TODO \"unprepare_chroot $COPYDEST <-i>\""

if [ ! "$CHROOTDIR" ]; then
  todo_dounmount
fi

eval "interactive $TODOY -r -h \"=== \$IAHEAD ===\" $TODO"

echo "Please Reboot now !" | tee -a $ERRLOG >&2
