#!/bin/bash

ANSWER="/tmp/.setup"
TITLE="Arch Linux Installation"
# use the first VT not dedicated to a running console
LOG="/dev/tty7"
# don't use /mnt because it's intended to mount other things there!
DESTDIR="/tmp/install"
EDITOR=

# name of the kernel image
VMLINUZ="vmlinuz26"
[ "$(cat /proc/cmdline | grep -w BOOT_IMAGE=.*lts)" ] && VMLINUZ="vmlinuz26-lts"
# name of kernel package
KERNELPKG="kernel26"
[ "$(cat /proc/cmdline | grep -w BOOT_IMAGE=.*lts)" ] && KERNELPKG="kernel26-lts"

# abstract the common pacman args
PACMAN="pacman --root ${DESTDIR} --config /tmp/pacman.conf --noconfirm --noprogressbar"
# downloader
DLPROG="wget"
# sources
SYNC_URL=
FILE_URL="file:///src/core-$(uname -m)/pkg"
MIRRORLIST="/etc/pacman.d/mirrorlist"
PACKAGES=

# destination of blockdevices in /sys
block=/sys/block

# partitions
PART_ROOT=
ROOTFS=""

# default filesystem specs (the + is bootable flag)
# <mountpoint>:<partsize>:<fstype>[:+]
DEFAULTFS="/boot:32:ext2:+ swap:256:swap /:7500:ext3 /home:*:ext3"

# install stages
S_SRC=0         # choose install medium
S_NET=0         # network configuration
S_CLOCK=0       # clock and timezone
S_PART=0        # partitioning
S_MKFS=0        # formatting
S_MKFSAUTO=0    # auto fs part/formatting
S_SELECT=0      # package selection
S_INSTALL=0     # package installation
S_CONFIG=0      # configuration editing
S_LILO=0        # TODO: kill this - if using lilo
S_GRUB=0        # using grub
S_BOOT=""       # bootloader installed (set to loader name instead of 1)

# menu item tracker- autoselect the next item
NEXTITEM=""

# DIALOG()
# an el-cheapo dialog wrapper
#
# parameters: see dialog(1)
# returns: whatever dialog did
DIALOG() {
    dialog --backtitle "$TITLE" --aspect 15 "$@"
    return $?
}

# chroot_mount()
# prepares target system as a chroot
#
chroot_mount()
{
    [ -e "${DESTDIR}/sys" ] || mkdir "${DESTDIR}/sys"
    [ -e "${DESTDIR}/proc" ] || mkdir "${DESTDIR}/proc"
    [ -e "${DESTDIR}/dev" ] || mkdir "${DESTDIR}/dev"
    mount -t sysfs sysfs "${DESTDIR}/sys"
    mount -t proc proc "${DESTDIR}/proc"
    mount -o bind /dev "${DESTDIR}/dev"
}

# chroot_umount()
# tears down chroot in target system
#
chroot_umount()
{
    umount $DESTDIR/proc
    umount $DESTDIR/sys
    umount $DESTDIR/dev
}

# getuuid()
# converts /dev/[hs]d?[0-9] devices to UUIDs
#
# parameters: device file
# outputs:    UUID on success
#             nothing on failure
# returns:    nothing
getuuid()
{
    if [ "${1%%/[hs]d?[0-9]}" != "${1}" -o "${1%%/md[0-9]}" != "${1}" ]; then
        echo "$(blkid -s UUID -o value ${1})"
    fi
}

# Check media on install packages
check_media() {
    ! [ "$(cat /proc/mounts | grep /dev/$dev)" ] && mount /dev/$dev $media >/dev/null 2>&1
    if [ -d $media/core-$(uname -m)/pkg ]; then
        SET_MEDIA=1
        break
    else
        umount $media >/dev/null 2>&1
    fi
}

# Get cdroms and removable devices
get_media() {
    media=/src
    SET_MEDIA=0
    #unmount media first, we may have leftovers ...
    umount $media  >/dev/null 2>&1
    # ide devices
    if [ "$SET_MEDIA" = "0" ]; then
        for dev in $(ls $block | egrep '^hd'); do
            if [ "$(cat $block/$dev/device/media)" = "cdrom" ]; then
                check_media
            fi
        done
    fi
    if [ "$SET_MEDIA" = "0" ]; then
        # scsi/sata and other devices
        for dev in $(ls $block | egrep '^sd|^sr|^scd|^sg'); do
            if [ "$(cat $block/$dev/device/type)" = "5" ]; then
                check_media
            fi
        done
    fi
    if [ "$SET_MEDIA" = "0" ]; then
        # usb devices with raw partition
        for dev in $(ls $block | egrep '^sd'); do
            if [ "$(cat $block/$dev/device/type)" = "0" -a "$(cat $block/$dev/removable)" = "1" -a ! "$(cat $block/$dev/size)" = "0" ]; then
                check_media
            fi
        done
    fi
}

#check on manual mounted source
manual_media() {
    if [ "$SET_MEDIA" = "0" ]; then
        DIALOG --msgbox "No source media was autodetected, please switch to another VC and manually mount the source media under /src.  If you manually mount to /src, make sure the packages are available under /src/core-$(uname -m)/pkg.\n\n" 15 55
    fi
    if [ ! -d /src/core-$(uname -m)/pkg ]; then
        DIALOG --msgbox "Package directory /src/core-$(uname -m)/pkg is missing!" 0 0
        return 1
    fi
}

findautoprepare() {
    # ide devices
    for dev in $(ls $block 2>/dev/null | egrep '^hd'); do
        if [ "$(cat $block/$dev/device/media)" = "disk" ]; then
            if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                    echo "/dev/$dev"
                    [ "$1" ] && echo $1
                fi
            fi
        fi
    done
    #scsi/sata devices
    for dev in $(ls $block 2>/dev/null | egrep '^sd'); do
        if ! [ "$(cat $block/$dev/device/type)" = "5" ]; then
            if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                    echo "/dev/$dev"
                    [ "$1" ] && echo $1
                fi
            fi
        fi
    done
    # cciss controllers
    if [ -d /dev/cciss ] ; then
        for dev in $(ls /dev/cciss | egrep -v 'p'); do
            echo "/dev/cciss/$dev"
            [ "$1" ] && echo $1
        done
    fi
    # Smart 2 controllers
    if [ -d /dev/ida ] ; then
        for dev in $(ls /dev/ida | egrep -v 'p'); do
                echo "/dev/ida/$dev"
                [ "$1" ] && echo $1
        done
    fi
}

finddisks() {
    # ide devices
    for dev in $(ls $block 2>/dev/null | egrep '^hd'); do
        if [ "$(cat $block/$dev/device/media)" = "disk" ]; then
            if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                    echo "/dev/$dev"
                    [ "$1" ] && echo $1
                fi
            fi
        fi
    done
    #scsi/sata devices
    for dev in $(ls $block 2>/dev/null | egrep '^sd'); do
        if ! [ "$(cat $block/$dev/device/type)" = "5" ]; then
            if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                    echo "/dev/$dev"
                    [ "$1" ] && echo $1
                fi
            fi
        fi
    done
    # cciss controllers
    if [ -d /dev/cciss ] ; then
        for dev in $(ls /dev/cciss | egrep -v 'p'); do
            echo "/dev/cciss/$dev"
            [ "$1" ] && echo $1
        done
    fi
    # Smart 2 controllers
    if [ -d /dev/ida ] ; then
        for dev in $(ls /dev/ida | egrep -v 'p'); do
                echo "/dev/ida/$dev"
                [ "$1" ] && echo $1
        done
    fi
    # dmraid devices
    if [ -d /dev/mapper ] ; then
        for fakeraid in $(dmraid -s -c); do
                if [ "$(echo $fakeraid | grep '_')" ]; then
                    echo "/dev/mapper/$fakeraid"
                    [ "$1" ] && echo $1
                fi
        done
    fi
    # partitionable raid
    for dev in $(cat /proc/mdstat 2>/dev/null | grep ^md_d[0-9] | sed 's#:.*##g'); do
        echo "/dev/$dev"
        [ "$1" ] && echo $1
    done
}

findpartitions() {
    for devpath in $(finddisks); do
        disk=$(basename $devpath)
        for part in $(ls $block/$disk 2>/dev/null | egrep ^$disk); do
            # exclude checks:
            #- part of raid device
            #  $(cat /proc/mdstat 2>/dev/null | grep $part)
            #- part of lvm2 device
            #  $(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2")
            #- part of luks device
            #  $(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LUKS")
            #- extended partition
            #  $(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")
            #- extended partition on raid partition device
            #  $(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk\p##g" 2>/dev/null | grep "5")
            if ! [ "$(cat /proc/mdstat 2>/dev/null | grep $part)" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2")" -o $(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LUKS") -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk\p##g") 2>/dev/null | grep "5")" ]; then
                if [ -d $block/$disk/$part ]; then
                    echo "/dev/$part"
                    [ "$1" ] && echo $1
                fi
            fi
        done
    done
    # device mapper devices, only show dmraid partitions, remove part of encrypted devices, remove part of lvm, remove part ot raid!
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"crypto_LUKS\"" | sed -e 's#:.*##g')"
        partofcrypt="$partofcrypt $k"
    done
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"LVM2_member\"" | sed -e 's#:.*##g')"
        partoflvm="$partoflvm $k"
    done
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g')"
        partofraid="$partofraid $k"
    done
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        if ! [ "$(dmraid -s -c | grep $devpath$)" -o "$(ls $partofcrypt 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(ls $partoflvm 2>/dev/null | grep /dev/mapper/$devpath$)" -o "$(ls $partofraid 2>/dev/null | grep /dev/mapper/$devpath$)" ]; then
            echo "/dev/mapper/$devpath"
            [ "$1" ] && echo $1
        fi
    done
    # include none partitionable raid md devices
    for devpath in $(ls -d /dev/md* 2>/dev/null | grep md[0-9]); do
        # exlude md partitions which are part of lvm
        if ! [ "$(blkid -c=/dev/null $devpath | grep "TYPE=\"LVM2_member\"")" -o "$(blkid -c=/dev/null $devpath | grep "TYPE=\"crypto_LUKS\"")" ]; then
                echo "$devpath"
                [ "$1" ] && echo $1
        fi
    done
    # inlcude cciss controllers
    if [ -d /dev/cciss ] ; then
        for dev in $(ls /dev/cciss | egrep 'p'); do
            echo "/dev/cciss/$dev"
            [ "$1" ] && echo $1
        done
    fi
    # inlcude Smart 2 controllers
    if [ -d /dev/ida ] ; then
        for dev in $(ls /dev/ida | egrep 'p'); do
            echo "/dev/ida/$dev"
            [ "$1" ] && echo $1
        done
    fi
}

# don't check on raid devices!
findbootloaderdisks() {
    if ! [ "$USE_DMRAID" = "1" ]; then
        # ide devices
        for dev in $(ls $block | egrep '^hd'); do
            if [ "$(cat $block/$dev/device/media)" = "disk" ]; then
                if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                    if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                        echo "/dev/$dev"
                        [ "$1" ] && echo $1
                    fi
                fi
            fi
        done
        #scsi/sata devices
        for dev in $(ls $block | egrep '^sd'); do
            if ! [ "$(cat $block/$dev/device/type)" = "5" ]; then
                if ! [ "$(cat $block/$dev/size)" = "0" ]; then
                    if ! [ "$(cat /proc/mdstat 2>/dev/null | grep "$dev\[")" -o "$(dmraid -rc | grep /dev/$dev)" ]; then
                        echo "/dev/$dev"
                        [ "$1" ] && echo $1
                    fi
                fi
            fi
        done
        # cciss controllers
        if [ -d /dev/cciss ] ; then
            for dev in $(ls /dev/cciss | egrep -v 'p'); do
                echo "/dev/cciss/$dev"
                [ "$1" ] && echo $1
            done
        fi
        # Smart 2 controllers
        if [ -d /dev/ida ] ; then
            for dev in $(ls /dev/ida | egrep -v 'p'); do
                    echo "/dev/ida/$dev"
                    [ "$1" ] && echo $1
            done
        fi
    else
    # dmraid devices
        if [ -d /dev/mapper ] ; then
            for fakeraid in $(dmraid -s -c); do
                if [ "$(echo $fakeraid | grep '_')" ]; then
                    echo "/dev/mapper/$fakeraid"
                    [ "$1" ] && echo $1
                fi
            done
        fi
    fi
}

# don't list raid devices, lvm2 and devicemapper!
findbootloaderpartitions() {
    if ! [ "$USE_DMRAID" = "1" ]; then
        for devpath in $(findbootloaderdisks); do
            disk=$(basename $devpath)
            for part in $(ls $block/$disk | egrep ^$disk); do
                # exclude checks:
                #- part of raid device
                #  $(cat /proc/mdstat 2>/dev/null | grep $part)
                #- part of lvm2 device
                #  $(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2")
                #- part of luks device
                #  $(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LUKS")
                #- extended partition
                #  $(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")
                #- extended partition on raid partition device
                #  $(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk\p##g" 2>/dev/null | grep "5")
                if ! [ "$(cat /proc/mdstat 2>/dev/null | grep $part)" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LVM2")" -o "$(blkid -c=/dev/null -o value -s TYPE /dev/$part | grep "LUKS")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk\p##g") 2>/dev/null | grep "5")" ]; then
                    if [ -d $block/$disk/$part ]; then
                        echo "/dev/$part"
                        [ "$1" ] && echo $1
                    fi
                fi
            done
        done
        # inlcude cciss controllers
        if [ -d /dev/cciss ] ; then
            for dev in $(ls /dev/cciss | egrep 'p'); do
                echo "/dev/cciss/$dev"
                [ "$1" ] && echo $1
            done
        fi
        # inlcude Smart 2 controllers
        if [ -d /dev/ida ] ; then
            for dev in $(ls /dev/ida | egrep 'p'); do
                echo "/dev/ida/$dev"
                [ "$1" ] && echo $1
            done
        fi
    else
        # only show dmraid partitions!
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"crypto_LUKS\"" | sed -e 's#:.*##g')"
            partofcrypt="$partofcrypt $k"
        done
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"LVM2_member\"" | sed -e 's#:.*##g')"
            partoflvm="$partoflvm $k"
        done
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            k="$(blkid -c=/dev/null /dev/mapper/$devpath 2>/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g')"
            partofraid="$partofraid $k"
        done
        for i in $(dmraid -s -c); do
            for devpath in $(echo /dev/mapper/$i*); do 
            if ! [ "$(dmraid -s -c | grep $(basename $devpath)$)" -o "$(ls $partofcrypt 2>/dev/null | grep $devpath$)" -o "$(ls $partoflvm 2>/dev/null | grep $devpath$)" -o "$(ls $partofraid 2>/dev/null | grep $devpath$)" ]; then
                echo "$devpath"
                [ "$1" ] && echo $1
            fi
        done
        done
    fi
}

get_grub_map() {
    rm /tmp/dev.map
    DIALOG --infobox "Generating GRUB device map...\nThis could take a while.\n\n Please be patient." 0 0
    $DESTDIR/sbin/grub --no-floppy --device-map /tmp/dev.map >/tmp/grub.log 2>&1 <<EOF
quit
EOF
}

get_grub_dmraid_map() {
    USE_DMRAID="1"
    rm /tmp/dev.map
    DIALOG --infobox "Generating GRUB dmraid device map...\nThis could take a while.\n\n Please be patient." 0 0
    majorhd=0
    for i in $(dmraid -s -c); do
        echo "(hd$majorhd) /dev/mapper/$i" >> /tmp/dev.map
        majorhd="$(($majorhd+1))"
    done
}

#get geometry of device for grub installation
get_chs() {
    realdev=""
    checkdev=""
    # we need the real device for geometry check!
    realdev="$(echo $bootdev | sed -e 's#,.*)#)#g')"
    checkdev=$(grep $realdev /tmp/dev.map | sed -e 's#.*\ ##g')
    CYLINDERS=$(sfdisk -G $checkdev | cut -d " " -f2)
    HEADS=$(sfdisk -G $checkdev | cut -d " " -f4)
    SECTORS=$(sfdisk -G $checkdev | cut -d " " -f6)
}

# we need symlinks for grub installation!
grub_dmraid_hack() {
    for i in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        if ! [ "$(dmraid -s -c | grep $i$)" ]; then
            rm -f /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
            ln -s /dev/mapper/$i  /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

# remove created symlinks
remove_grub_dmraid_hack(){
    for i in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        if ! [ "$(dmraid -s -c | grep $i$)" ]; then
            rm -f /dev/mapper/$(echo $i | sed -n -e "s/\(.*\)p/\1/p")
        fi
    done
}

mapdev() {
    partition_flag=0
    device_found=0
    devs=$(cat /tmp/dev.map | grep -v /dev/fd | sed 's/ *\t/ /' | sed ':a;$!N;$!ba;s/\n/ /g')
    # check if we use hd or sd device
    if ! [ "$(echo $1 | grep /dev/sd)" -o "$(echo $1 | grep /dev/hd)" ]; then
        linuxdevice=$(echo $1 | sed -e 's#p[0-9].*$##')
    else
        linuxdevice=$(echo $1 | sed -e 's#[0-9].*$##g')
    fi
    if ! [ "$(echo $1 | grep /dev/sd)" -o "$(echo $1 | grep /dev/hd)" ]; then
        if [ "$(echo $1 | egrep 'p[0-9].*$')" ]; then
            pnum=$(echo $1 | sed -e 's#.*p##g')
            pnum=$(($pnum-1))
            partition_flag=1
        fi
    else
        if [ "$(echo $1 | egrep '[0-9]$')" ]; then
            # /dev/hdXY
            pnum=$(echo $1 | cut -b9-)
            pnum=$(($pnum-1))
            partition_flag=1
        fi
    fi
    for  dev in $devs; do
        if [ "(" = $(echo $dev | cut -b1) ]; then
            grubdevice="$dev"
        else
            if [ "$dev" = "$linuxdevice" ]; then
                device_found=1
                break
            fi
        fi
    done
    if [ "$device_found" = "1" ]; then
        if [ "$partition_flag" = "0" ]; then
            echo "$grubdevice"
        else
            grubdevice_stringlen=${#grubdevice}
            grubdevice_stringlen=$(($grubdevice_stringlen - 1))
            grubdevice=$(echo $grubdevice | cut -b1-$grubdevice_stringlen)
            echo "$grubdevice,$pnum)"
        fi
    else
        echo "DEVICE NOT FOUND"
    fi
}

printk()
{
    case $1 in
        "on")  echo 4 >/proc/sys/kernel/printk ;;
        "off") echo 0 >/proc/sys/kernel/printk ;;
    esac
}

getdest() {
    [ "$DESTDIR" ] && return 0
    DIALOG --inputbox "Enter the destination directory where your target system is mounted" 8 65 "/tmp/install" 2>$ANSWER || return 1
    DESTDIR=$(cat $ANSWER)
}

# geteditor()
# prompts the user to choose an editor
# sets EDITOR global variable
#
geteditor() {
    if ! [ $(which vi) ]; then
        DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
            "1" "nano (easier)" 2>$ANSWER
    else
        DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
            "1" "nano (easier)" \
            "2" "vi" 2>$ANSWER
    fi
    case $(cat $ANSWER) in
        "1") EDITOR="nano" ;;
        "2") EDITOR="vi" ;;
        *)   EDITOR="nano" ;;
    esac
}

# _mkfs()
# Create and mount filesystems in our destination system directory.
#
# args:
#  domk: Whether to make the filesystem or use what is already there
#  device: Device filesystem is on
#  fstype: type of filesystem located at the device (or what to create)
#  dest: Mounting location for the destination system
#  mountpoint: Mount point inside the destination system, e.g. '/boot'

# returns: 1 on failure
_mkfs() {
    local _domk=$1
    local _device=$2
    local _fstype=$3
    local _dest=$4
    local _mountpoint=$5

    # we have two main cases: "swap" and everything else.
    if [ "${_fstype}" = "swap" ]; then
        swapoff ${_device} >/dev/null 2>&1
        if [ "${_domk}" = "yes" ]; then
            mkswap ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                DIALOG --msgbox "Error creating swap: mkswap ${_device}" 0 0
                return 1
            fi
        fi
        swapon ${_device} >$LOG 2>&1
        if [ $? != 0 ]; then
            DIALOG --msgbox "Error activating swap: swapon ${_device}" 0 0
            return 1
        fi
    else
        # make sure the fstype is one we can handle
        local knownfs=0
        for fs in xfs jfs reiserfs ext2 ext3 ext4 ntfs-3g vfat; do
            [ "${_fstype}" = "${fs}" ] && knownfs=1 && break
        done
        if [ $knownfs -eq 0 ]; then
            DIALOG --msgbox "unknown fstype ${_fstype} for ${_device}" 0 0
            return 1
        fi
        # if we were tasked to create the filesystem, do so
        if [ "${_domk}" = "yes" ]; then
            local ret
            case ${_fstype} in
                xfs)      mkfs.xfs -f ${_device} >$LOG 2>&1; ret=$? ;;
                jfs)      yes | mkfs.jfs ${_device} >$LOG 2>&1; ret=$? ;;
                reiserfs) yes | mkreiserfs ${_device} >$LOG 2>&1; ret=$? ;;
                ext2)     mkfs.ext2 ${_device} >$LOG 2>&1; ret=$? ;;
                ext3)     mke2fs -t ext3 ${_device} >$LOG 2>&1; ret=$? ;;
                ext4)     mke2fs -t ext4 ${_device} >$LOG 2>&1; ret=$? ;;
                ntfs-3g)  mkfs.ntfs ${_device} >$LOG 2>&1; ret=$? ;;
                vfat)     mkfs.vfat ${_device} >$LOG 2>&1; ret=$? ;;
                # don't handle anything else here, we will error later
            esac
            if [ $ret != 0 ]; then
                DIALOG --msgbox "Error creating filesystem ${_fstype} on ${_device}" 0 0
                return 1
            fi
            sleep 2
        fi
        # create our mount directory
        mkdir -p ${_dest}${_mountpoint}
        # mount the bad boy
        mount -t ${_fstype} ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            DIALOG --msgbox "Error mounting ${_dest}${_mountpoint}" 0 0
            return 1
        fi
    fi

    # add to temp fstab
    if [ "$UUIDPARAMETER" = "yes" ]; then
        local _uuid="$(getuuid ${_device})"
        if [ -n "${_uuid}" ]; then
            _device="UUID=${_uuid}"
        fi
        echo -n "${_device} ${_mountpoint} ${_fstype} defaults 0 " >>/tmp/.fstab
    else
        echo -n "${_device} ${_mountpoint} ${_fstype} defaults 0 " >>/tmp/.fstab
    fi
    if [ "${_fstype}" = "swap" ]; then
        echo "0" >>/tmp/.fstab
    else
        echo "1" >>/tmp/.fstab
    fi
}

# Get a list of available disks for use in the "Available disks" dialogs. This
# will print the mountpoints as follows, getting size info from /sys:
#   /dev/sda: 64000 MB
#   /dev/sdb: 64000 MB
_getavaildisks()
{
    for i in $(finddisks); do
        #if ! [ "$(pvs -o pv_name --noheading | grep $i)" ]; then
            if [ $(echo "$i" | grep 'mapper') ]; then
                echo -n "$i : "; echo $(($(expr 512 '*' $(dmsetup status $i | cut -f2 -d " "))/1000000)) MB; echo "\n"
            else
                echo -n "$i : "; echo $(($(expr 512 '*' $(cat /sys/block/$(basename $i)/size))/1000000)) MB; echo "\n"
            fi
        #fi
    done
}

# Get a list of available partitions for use in the "Available Mountpoints" dialogs. This
# will print the mountpoints as follows, getting size info from /sys:
#   /dev/sda1: 640 MB
#   /dev/sdb2: 640 MB
_getavailpartitions()
{
    for i in $(findpartitions); do
        if [ $(echo "$i" | grep '/md_d[0-9]') ]; then
            echo -n "$i : "; echo $(($(expr 512 '*' $(cat /sys/block/$(basename $i | sed -e 's#p.*##g')/$(basename $i)/size))/1000000)) MB; echo "\n"
        elif [ $(echo "$i" | grep 'md') ]; then
            echo -n "$i : "; echo $(($(expr 512 '*' $(cat /sys/block/$(basename $i)/size))/1000000)) MB; echo "\n"
        elif [ $(echo "$i" | grep 'mapper') ]; then
            if [ "$(cryptsetup status $i 2>/dev/null)" ]; then
                echo -n "$i: "; echo $(($(expr 512 '*' $(cryptsetup status $(basename $i) | grep " size:" | sed -e 's#sectors##g' -e 's#size:##g'))/1000000)) MB; echo "\n"
            elif [ "$(dmsetup info $i | grep 'DMRAID')"  ]; then
                [ $(echo $i | grep 'p*[0-9]$') ] && echo -n "$i : "; echo $(($(expr 512 '*' $(dmsetup status $i | cut -f2 -d " "))/1000000)) MB; echo "\n"
            else
                echo -n "$i : "; echo $(lvs -o lv_size --noheading --units m $i | sed -e 's#M##g') MB; echo "\n"
            fi
        else
            echo -n "$i: "; echo $(($(expr 512 '*' $(cat /sys/block/$(basename $i | sed -e 's#[0-9].*##g')/$(basename $i)/size))/1000000)) MB; echo "\n"
        fi
    done
}

# Disable swap and all mounted partitions for the destination system. Unmount
# the destination root partition last!
_umountall()
{
    DIALOG --infobox "Disabling swapspace, unmounting already mounted disk devices..." 0 0
    swapoff -a >/dev/null 2>&1
    umount $(mount | grep -v "${DESTDIR} " | grep "${DESTDIR}" | sed 's|\ .*||g') >/dev/null 2>&1
    umount $(mount | grep "${DESTDIR} " | sed 's|\ .*||g') >/dev/null 2>&1
}

# Disable all software raid devices
_stopmd()
{
    if [ "$(cat /proc/mdstat 2>/dev/null | grep ^md)" ]; then
        DISABLEMD=""
        DIALOG --defaultno --yesno "Setup detected already running raid devices, do you want to disable them completely?" 0 0 && DISABLEMD="1"
        if [ "$DISABLEMD" = "1" ]; then
            DIALOG --infobox "Disabling all software raid devices..." 0 0
            for i in $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*##g'); do
                mdadm --manage --stop /dev/$i > $LOG
            done
            DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
            for i in $(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g'); do
                mdadm --zero-superblock $i > $LOG
            done
        fi
    fi
    DISABLEMDSB=""
    if [ "$(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"")" ]; then
        DIALOG --defaultno --yesno "Setup detected superblock of raid devices, do you want to clean the superblock of them?" 0 0 && DISABLEMDSB="1"
        if [ "$DISABLEMDSB" = "1" ]; then
            DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
            for i in $(blkid -c=/dev/null | grep "TYPE=\"linux_raid_member\"" | sed -e 's#:.*##g'); do
                mdadm --zero-superblock $i > $LOG
            done
        fi
    fi
}

# Disable all lvm devices
_stoplvm()
{
    DISABLELVM=""
    DETECTED_LVM=""
    LV_VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator -)"
    LV_GROUPS="$(vgs -o vg_name --noheading)"
    LV_PHYSICAL="$(pvs -o pv_name --noheading)"
    ! [ "$LV_VOLUMES" = "" ] && DETECTED_LVM=1
    ! [ "$LV_GROUPS" = "" ] && DETECTED_LVM=1
    ! [ "$LV_PHYSICAL" = "" ] && DETECTED_LVM=1
    if [ "$DETECTED_LVM" = "1" ]; then
        DIALOG --defaultno --yesno "Setup detected lvm volumes, volume groups or physical devices, do you want to remove them completely?" 0 0 && DISABLELVM="1"
    fi
    if [ "$DISABLELVM" = "1" ]; then
        DIALOG --infobox "Removing logical volumes ..." 0 0
        for i in $LV_VOLUMES; do
            lvremove -f /dev/mapper/$i 2>/dev/null> $LOG
        done
        DIALOG --infobox "Removing logical groups ..." 0 0
        for i in $LV_GROUPS; do
            vgremove -f $i 2>/dev/null > $LOG
        done
        DIALOG --infobox "Removing physical volumes ..." 0 0
        for i in $LV_PHYSICAL; do
            pvremove -f $i 2>/dev/null > $LOG
        done
    fi
}

# Disable all luks encrypted devices
_stopluks()
{
    DISABLELUKS=""
    DETECTED_LUKS=""
    LUKSDEVICE=""
    LUKS_DEVICES="$(ls /dev/mapper/ | grep -v control)"
    for i in $LUKS_DEVICES; do
        cryptsetup status $i 2>/dev/null && LUKSDEVICE="$LUKSDEVICE $i"
    done
    ! [ "$LUKSDEVICE" = "" ] && DETECTED_LUKS=1
    if [ "$DETECTED_LUKS" = "1" ]; then
        DIALOG --defaultno --yesno "Setup detected luks encrypted devices, do you want to remove them completely?" 0 0 && DISABLELUKS="1"
    fi
    if [ "$DISABLELUKS" = "1" ]; then
        DIALOG --infobox "Removing luks encrypted devices ..." 0 0
        for i in $LUKSDEVICE; do
            LUKS_REAL_DEVICE="$(echo $(cryptsetup status $i | grep device: | sed -e 's#device:##g'))"
            cryptsetup remove $i > $LOG
            # delete header from device
            wipefs -a $LUKS_REAL_DEVICE > $LOG
        done
    fi
    [ -e /tmp/.crypttab ] && rm /tmp/.crypttab
}

#_dmraid_update
_dmraid_update()
{
    DIALOG --infobox "Deactivating dmraid devices ..." 0 0
    dmraid -an >/dev/null 2>&1
    if [ "$DETECTED_LVM" = "1" -o "$DETECTED_LUKS" = "1" ]; then
	DIALOG --defaultno --yesno "Setup detected running dmraid devices and/or running lvm2, luks encrypted devices. If you reduced/deleted partitions on your dmraid device a complete reset of devicemapper devices is needed. This will reset also your created lvm2 or encrypted devices. Are you sure you want to do this?" 0 0 && RESETDM="1"
	if [ "$RESETDM" = "1" ]; then
            DIALOG --infobox "Resetting devicemapper devices ..." 0 0
	    dmsetup remove_all >/dev/null 2>&1
	fi
    else
        DIALOG --infobox "Resetting devicemapper devices ..." 0 0
	dmsetup remove_all >/dev/null 2>&1
    fi
    DIALOG --infobox "Reactivating dmraid devices ..." 0 0
    dmraid -ay -Z >/dev/null 2>&1
}

#helpbox for raid
_helpraid()
{
DIALOG --msgbox "LINUX SOFTWARE RAID SUMMARY:\n
-----------------------------\n\n
Linear mode:\n
You have two or more partitions which are not necessarily the same size\n
(but of course can be), which you want to append to each other.\n
Spare-disks are not supported here. If a disk dies, the array dies with\n
it.\n\n
RAID-0:\n
You have two or more devices, of approximately the same size, and you want\n
to combine their storage capacity and also combine their performance by\n
accessing them in parallel. Like in Linear mode, spare disks are not\n
supported here either. RAID-0 has no redundancy, so when a disk dies, the\n
array goes with it.\n\n
RAID-1:\n
You have two devices of approximately same size, and you want the two to\n
be mirrors of each other. Eventually you have more devices, which you\n
want to keep as stand-by spare-disks, that will automatically become a\n
part of the mirror if one of the active devices break.\n\n
RAID-5:\n
You have three or more devices of roughly the same size, you want to\n
combine them into a larger device, but still to maintain a degree of\n
redundancy fordata safety. Eventually you have a number of devices to use\n
as spare-disks, that will not take part in the array before another device\n
fails. If you use N devices where the smallest has size S, the size of the\n
entire array will be (N-1)*S. This \"missing\" space is used for parity\n
(redundancy) information. Thus, if any disk fails, all data stay intact.\n
But if two disks fail, all data is lost.\n\n
RAID-10:\n
Shorthand for RAID1+0, a mirrored striped array and needs a minimum of\n
two disks. It provides superior data security and can survive multiple\n
disk failures. The main disadvantage is cost, because 50% of your\n
storage is duplication." 0 0
}

# Create raid
_raid()
{
    MDFINISH=""
    while [ "$MDFINISH" != "DONE" ]; do
        : >/tmp/.raid
        : >/tmp/.raid-spare
        # check for devices
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        #hell yeah, this is complicated! kill software raid devices already in use.
        ALREADYINUSE=$(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*linear##g' -e 's# :.*raid[0-9][0-9]##g' -e 's# :.*raid[0-9]##g' -e 's#\[[0-9]\]##g')
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#/dev/$i\ _##g" -e "s#/dev/$i\p[0-9]\ _##g")
            k=$(echo /dev/$i | sed -e 's#[0-9]##g')
            if ! [ $(echo $k | grep ^md) ]; then
                PARTS=$(echo $PARTS | sed -e "s#$k\ _##g")
            fi
        done
        # skip encrypted mapper devices which contain raid devices
        ALREADYINUSE=""
        for i in $(ls /dev/mapper/* 2>/dev/null | grep -v control); do
            cryptsetup status $i 2>/dev/null | grep -q "device:.*/dev/md" && ALREADYINUSE="$ALREADYINUSE $i"
        done
        # skip lvm with raid devices
        for devpath in $(pvs -o pv_name --noheading); do
            # skip simple lvm device with raid device
            if [ "$(echo $devpath | grep /dev/md)" ]; then
                killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
            fi
            # skip encrypted raid device
            if [ "$(echo $devpath | grep dm-)" ]; then
                if [ "$(cryptsetup status $(basename $devpath) | grep "device:.*/dev/md")" ]; then
                   killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                   ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
                fi
            fi
        done
        # skip already encrypted volume devices with raid device
        for devpath in $(ls /dev/mapper/ 2>/dev/null | grep -v control); do
            realdevice="$(cryptsetup status $devpath 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
            if [ "$(lvs $realdevice 2>/dev/null)" ]; then
                vg="$(echo $(lvs -o vg_name --noheading $realdevice))"
                if [ "$(pvs -o pv_name,vg_name --noheading | grep "$vg$" | grep "/dev/md")" ]; then
                   ALREADYINUSE="$ALREADYINUSE /dev/mapper/$devpath"
                fi
            fi
        done
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#$i\ _##g")
        done
        # break if all devices are in use
        if [ "$PARTS" = "" ]; then
            DIALOG --msgbox "All devices in use. No more devices left for new creation." 0 0
            return 1
        fi
        # enter raid device name
        RAIDDEVICE=""
        while [ "${RAIDDEVICE}" = "" ]; do
            DIALOG --inputbox "Enter the node name for the raiddevice:\n/dev/md[number]\n/dev/md0\n/dev/md1\n\n" 15 65 "/dev/md0" 2>$ANSWER || return 1
            RAIDDEVICE=$(cat $ANSWER)
            if [ "$(cat /proc/mdstat 2>/dev/null | grep "^$(echo $RAIDDEVICE | sed -e 's#/dev/##g')")" ]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical node names! Please enter another name." 8 65
                RAIDDEVICE=""
            fi
        done
        RAIDLEVELS="linear - raid0 - raid1 - raid5 - raid10 -"
        DIALOG --menu "Select the raid level you want to use" 21 50 13 $RAIDLEVELS 2>$ANSWER || return 1
        LEVEL=$(cat $ANSWER)
        # raid5 and raid10 support parity parameter
        PARITY=""
        if [ "$LEVEL" = "raid5" -o "$LEVEL" = "raid10" ]; then
            PARITYLEVELS="left-asymmetric - left-symmetric - right-asymmetric - right-symmetric -"
            DIALOG --menu "Select the parity layout you want to use (default is left-symmetric)" 21 50 13 $PARITYLEVELS 2>$ANSWER || return 1
            PARTIY=$(cat $ANSWER)
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
        # select the first device to use, no missing option available!
        RAIDNUMBER=1
        DIALOG --menu "Select device $RAIDNUMBER" 21 50 13 $PARTS 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
        echo "$PART" >>/tmp/.raid
        while [ "$PART" != "DONE" ]; do
            RAIDNUMBER=$(($RAIDNUMBER + 1))
            # clean loop from used partition and options
            PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g" -e "s#${PART}[0-9]\ _##g" -e "s#$(echo ${PART} | sed -e 's#[0-9]##g')\ _##g" -e 's#MISSING\ _##g' -e 's#SPARE\ _##g')"
            # raid0 doesn't support missing devices
            ! [ "$LEVEL" = "raid0" -o "$LEVEL" = "linear" ] && MDEXTRA="MISSING _"
            # add more devices
            DIALOG --menu "Select additional device $RAIDNUMBER" 21 50 13 $PARTS $MDEXTRA DONE _ 2>$ANSWER || return 1
            PART=$(cat $ANSWER)
            SPARE=""
            ! [ "$LEVEL" = "raid0" -o "$LEVEL" = "linear" ] && DIALOG --yesno --defaultno "Would you like to use $PART as spare device?" 0 0 && SPARE="1"
            [ "$PART" = "DONE" ] && break
            if [ "$PART" = "MISSING" ]; then
                DIALOG --yesno "Would you like to create a degraded raid on $RAIDDEVICE?" 0 0 && DEGRADED="missing"
                echo "$DEGRADED" >>/tmp/.raid
            else
                if [ "$SPARE" = "1" ]; then
                    echo "$PART" >>/tmp/.raid-spare
                else
                    echo "$PART" >>/tmp/.raid
                fi
            fi
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create $RAIDDEVICE like this?\n\nLEVEL:\n$LEVEL\n\nDEVICES:\n$(for i in $(cat /tmp/.raid); do echo "$i\n";done)\nSPARES:\n$(for i in $(cat /tmp/.raid-spare); do echo "$i\n";done)" 0 0 && MDFINISH="DONE"
    done
    _createraid
}

# Create raid partitions
_raidpartitions()
{
    MDFINISH=""
    while [ "$MDFINISH" != "DONE" ]; do
        : >/tmp/.raid
        : >/tmp/.raid-spare
        # check for devices
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        #hell yeah, this is complicated! kill software raid devices already in use.
        ALREADYINUSE=$(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*linear##g' -e 's# :.*raid[0-9][0-9]##g' -e 's# :.*raid[0-9]##g' -e 's#\[[0-9]\]##g')
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#/dev/$i\ _##g" -e "s#/dev/$i\p[0-9]\ _##g")
            k=$(echo /dev/$i | sed -e 's#[0-9]##g')
            if ! [ $(echo $k | grep ^md) ]; then
                PARTS=$(echo $PARTS | sed -e "s#$k\ _##g")
            fi
        done
        # skip encrypted mapper devices which contain raid devices!
        ALREADYINUSE=""
        for i in $(ls /dev/mapper/*); do
            cryptsetup status $i 2>/dev/null | grep -q "device:.*/dev/md.*" && ALREADYINUSE="$ALREADYINUSE $i"
        done
        # skip lvm with raid devices
        for devpath in $(pvs -o pv_name --noheading); do
            # skip simple lvm with raid device
            if [ "$(echo $devpath | grep /dev/md)" ]; then
                killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
            fi
            # skip encrypted raid device
            if [ "$(echo $devpath | grep dm-)" ]; then
                if [ "$(cryptsetup status $(basename $devpath) | grep "device:.*/dev/md")" ]; then
                   killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                   ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
                fi
            fi
        done
        # skip already encrypted volume devices with raid device
        for devpath in $(ls /dev/mapper/ 2>/dev/null | grep -v control); do
            realdevice="$(cryptsetup status $devpath 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
            if [ "$(lvs $realdevice 2>/dev/null)" ]; then
                vg="$(echo $(lvs -o vg_name --noheading $realdevice))"
                if [ "$(pvs -o pv_name,vg_name --noheading | grep "$vg$" | grep "/dev/md")" ]; then
                   ALREADYINUSE="$ALREADYINUSE /dev/mapper/$devpath"
                fi
            fi
        done
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#$i\ _##g")
        done
        # break if all devices are in use
        if [ "$PARTS" = "" ]; then
            DIALOG --msgbox "All devices in use. No more devices left for new creation." 0 0
            return 1
        fi
        # enter raid device name
        RAIDDEVICE=""
        while [ "${RAIDDEVICE}" = "" ]; do
            DIALOG --inputbox "Enter the node name for partitionable raiddevice:\n/dev/md_d[number]\n/dev/md_d0\n/dev/md_d1" 15 65 "/dev/md_d0" 2>$ANSWER || return 1
            RAIDDEVICE=$(cat $ANSWER)
            if [ "$(cat /proc/mdstat 2>/dev/null | grep "^$(echo $RAIDDEVICE | sed -e 's#/dev/##g')")" ]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical node names! Please enter another name." 8 65
                RAIDDEVICE=""
            fi
        done
        RAIDLEVELS="linear - raid0 - raid1 - raid5 - raid10 -"
        DIALOG --menu "Select the raid level you want to use" 21 50 13 $RAIDLEVELS 2>$ANSWER || return 1
        LEVEL=$(cat $ANSWER)
        # raid5 and raid10 support parity parameter
        PARITY=""
        if [ "$LEVEL" = "raid5" -o "$LEVEL" = "raid10" ]; then
            PARITYLEVELS="left-asymmetric - left-symmetric - right-asymmetric - right-symmetric -"
            DIALOG --menu "Select the parity layout you want to use (default is left-symmetric)" 21 50 13 $PARITYLEVELS 2>$ANSWER || return 1
            PARTIY=$(cat $ANSWER)
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
        # select the first device to use, no missing option available!
        RAIDNUMBER=1
        DIALOG --menu "Select device $RAIDNUMBER" 21 50 13 $PARTS 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
        echo "$PART" >>/tmp/.raid
        while [ "$PART" != "DONE" ]; do
            RAIDNUMBER=$(($RAIDNUMBER + 1))
            # clean loop from used partition and options
            PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g" -e "s#${PART}[0-9]\ _##g" -e "s#$(echo ${PART} | sed -e 's#[0-9]##g')\ _##g" -e 's#MISSING\ _##g' -e 's#SPARE\ _##g')"
            # raid0 doesn't support missing devices
            ! [ "$LEVEL" = "raid0" -o "$LEVEL" = "linear" ] && MDEXTRA="MISSING _"
            # add more devices
            DIALOG --menu "Select additional device $RAIDNUMBER" 21 50 13 $PARTS $MDEXTRA DONE _ 2>$ANSWER || return 1
            PART=$(cat $ANSWER)
            SPARE=""
            ! [ "$LEVEL" = "raid0" -o "$LEVEL" = "linear" ] && DIALOG --yesno --defaultno "Would you like to use $PART as spare device?" 0 0 && SPARE="1"
            [ "$PART" = "DONE" ] && break
            if [ "$PART" = "MISSING" ]; then
                DIALOG --yesno "Would you like to create a degraded raid on $RAIDDEVICE?" 0 0 && DEGRADED="missing"
                echo "$DEGRADED" >>/tmp/.raid
            else
                if [ "$SPARE" = "1" ]; then
                    echo "$PART" >>/tmp/.raid-spare
                else
                    echo "$PART" >>/tmp/.raid
                fi
            fi
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create $RAIDDEVICE like this?\n\nLEVEL:\n$LEVEL\n\nDEVICES:\n$(for i in $(cat /tmp/.raid); do echo "$i\n";done)\nSPARES:\n$(for i in $(cat /tmp/.raid-spare); do echo "$i\n";done)" 0 0 && MDFINISH="DONE"
    done
    _createraid
}

# create raid device
_createraid()
{
    DEVICES="$(echo -n $(cat /tmp/.raid))"
    SPARES="$(echo -n $(cat /tmp/.raid-spare))"
    # combine both if spares are available, spares at the end!
    [ -n $SPARES ] && DEVICES="$DEVICES $SPARES"
    # get number of devices
    RAID_DEVICES="$(cat /tmp/.raid | wc -l)"
    SPARE_DEVICES="$(cat /tmp/.raid-spare | wc -l)"
    # generate options for mdadm
    RAIDOPTIONS="--force --run --level=$LEVEL"
    [ "$(echo $RAIDDEVICE | grep /md_d[0-9])" ] && RAIDOPTIONS="$RAIDOPTIONS -a mdp"
    ! [ "$RAID_DEVICES" = "0" ] && RAIDOPTIONS="$RAIDOPTIONS --raid-devices=$RAID_DEVICES"
    ! [ "$SPARE_DEVICES" = "0" ] && RAIDOPTIONS="$RAIDOPTIONS --spare-devices=$SPARE_DEVICES"
    ! [ "$PARITY" = "" ] && RAIDOPTIONS="$RAIDOPTIONS --layout=$PARITY"
    DIALOG --infobox "Creating $RAIDDEVICE..." 0 0
    mdadm --create $RAIDDEVICE $RAIDOPTIONS $DEVICES >$LOG 2>&1
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error creating $RAIDDEVICE (see $LOG for details)." 0 0
        return 1
    fi
    if [ "$(echo $RAIDDEVICE | grep /md_d[0-9])" ]; then
        DIALOG --msgbox "Now you'll be put into the cfdisk program where you can partition your raiddevice to your needs." 18 70
        cfdisk $RAIDDEVICE
    fi
    # writing raid information to partition table
    if [ "$(echo $RAIDDEVICE | grep /md_d[0-9])" ]; then
        for i in $(sfdisk -l $RAIDDEVICE | grep ^/dev | grep -v Empty | grep -v Extended | sed -e 's# .*##g'); do
            # output will be /dev/md_d0*
            # get device name
            k=$(echo $i | sed -e 's#p[0-9]##g')
            # get partition number of device
            l=$(echo $i | sed -e 's#.*p##g')
            DIALOG --infobox "Changing device $k$l to raid..." 0 0
            sfdisk --change-id $k $l fd >$LOG 2>&1
        done
    else
        for i in $(cat /tmp/.raid | grep -v missing); do
            # get device name
            if ! [ "$(echo $i | grep /dev/sd)" -o "$(echo $i | grep /dev/hd)" ]; then
                k=$(echo $i | sed -e 's#p[0-9].*$##')
            else
                k=$(echo $i | sed -e 's#[0-9].*$##g')
            fi
            # get partition number of device
            if ! [ "$(echo $i | grep /dev/sd)" -o "$(echo $i | grep /dev/hd)" ]; then
                if [ "$(echo $i | egrep 'p[0-9].*$')" ]; then
                    l=$(echo $i | sed -e 's#.*p##g')
                fi
            else
                if [ "$(echo $i | egrep '[0-9]$')" ]; then
                    # /dev/hdXY
                    l=$(echo $i | cut -b9-)
                fi
            fi
            DIALOG --infobox "Changing device $k$l to raid..." 0 0
            # only change id where it is possible!
            if [ "$(echo /dev/mapper/$(dmraid -s -c) | grep $i)" -o "$(echo $i | grep /dev/sd)" -o "$(echo $i | grep /dev/hd)" -o "$(echo $i | grep /dev/ida/)" -o "$(echo $i | grep /dev/cciss/)" ]; then
                sfdisk --change-id $k $l fd >$LOG 2>&1
            fi
        done
    fi
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error changing partition $k$l to raid (see $LOG for details)." 0 0
        return 1
    fi
}

# help for lvm
_helplvm()
{
DIALOG --msgbox "LOGICAL VOLUME SUMMARY:\n
-----------------------------\n\n
LVM is a Logical Volume Manager for the Linux kernel. With LVM you can\n
abstract your storage space and have \"virtual partitions\" which are easier\n
to modify.\n\nThe basic building block of LVM are:\n
- Physical volume (PV):\n
  Partition on hard disk (or even hard disk itself or loopback file) on\n
  which you can have virtual groups. It has a special header and is\n
  divided into physical extents. Think of physical volumes as big building\n
  blocks which can be used to build your hard drive.\n
- Volume group (VG):\n 
  Group of physical volumes that are used as storage volume (as one disk).\n
  They contain logical volumes. Think of volume groups as hard drives.\n 
- Logical volume(LV):\n
  A \"virtual/logical partition\" that resides in a volume group and is\n 
  composed of physical extents. Think of logical volumes as normal\n
  partitions." 0 0
}

# Creates physical volume
_createpv()
{
    PVFINISH=""
    while [ "$PVFINISH" != "DONE" ]; do
        : >/tmp/.pvs-create
        PVDEVICE=""
        #PARTS=$(finddisks _)
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        # skip volume devices
        for i in $(ls /dev/mapper/* | grep -v control); do
            [ "$(lvs $i 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE $i"
        done
        # skip already encrypted volume devices
        for devpath in $(ls /dev/mapper/ 2>/dev/null | grep -v control); do
            realdevice="$(cryptsetup status $devpath 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
            if ! [ "$realdevice" = "" ]; then
                [ "$(lvs $realdevice 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE /dev/mapper/$devpath"
            fi
        done
        # skip md devices, which already have lvm devices!
        for i in $PARTS; do
            mdcheck="$(echo $i | sed -e 's#/dev/##g')"
            if ! [ "$(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null)" = "" ]; then
                for k in $(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null); do
                    # check encrypted volume
                    realdevice="$(cryptsetup status $(cat $k/dm/name) 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
                    [ "$(lvs $realdevice 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                    # check on normal lvs
                    [ "$(lvs /dev/mapper/$(cat $k/dm/name) 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                done
            fi
        done
        # skip md partition devices, which already have lvm devices!
        for i in $PARTS; do
            mdcheck="$(echo $i | grep /dev/md_d | sed -e 's#p.*##g' -e 's#/dev/##g')"
            if [ "$(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null)" != "" -a "$mdcheck" != "" ]; then
                for k in $(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null); do
                    # check encrypted volume
                    realdevice="$(cryptsetup status $(cat $k/dm/name) 2>/dev/null | grep "device:.*/dev/mapper/" | sed -e 's#.*\ ##g')"
                    [ "$(lvs $realdevice 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                   # check on normal lvs
                    [ "$(lvs /dev/mapper/$(cat $k/dm/name) 2>/dev/null)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                done
            fi
        done
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#$i\ _##g")
        done
        # break if all devices are in use
        if [ "$PARTS" = "" ]; then
            DIALOG --msgbox "No devices left for physical volume creation." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
        # select the first device to use
        DEVNUMBER=1
        DIALOG --menu "Select device number $DEVNUMBER for physical volume" 21 50 13 $PARTS 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
        echo "$PART" >>/tmp/.pvs-create
        while [ "$PART" != "DONE" ]; do
            DEVNUMBER=$(($DEVNUMBER + 1))
            # clean loop from used partition and options
            PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g" -e "s#${PART}[0-9]\ _##g" -e "s#$(echo ${PART} | sed -e 's#[0-9]##g')\ _##g")"
            # add more devices
            DIALOG --menu "Select additional device number $DEVNUMBER for physical volume" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
            PART=$(cat $ANSWER)
            [ "$PART" = "DONE" ] && break
            echo "$PART" >>/tmp/.pvs-create
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create physical volume on devices below?\n$(cat /tmp/.pvs-create | sed -e 's#$#\\n#g')" 0 0 && PVFINISH="DONE"
    done
    DIALOG --infobox "Creating physical volume on $PART..." 0 0
    PART="$(echo -n $(cat /tmp/.pvs-create))"
    pvcreate $PART >$LOG 2>&1
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error creating physical volume on $PART (see $LOG for details)." 0 0
        return 1
    fi
}

#find physical volumes that are not in use
findpv()
{
    for dev in $(pvs -o pv_name --noheading);do
        if [ "$(pvs -o vg_name --noheading $dev)" = "      " ]; then
            #if [ "$(echo "$dev" | grep "dm-")" ]; then
            #    getsymlink="$(readlink $dev)"
            #    correctdevice="$(echo $getsymlink | sed -e 's#\.\.#/dev#g')"
            #    echo "$correctdevice"
            #    [ "$1" ] && echo $1
            #else
                echo "$dev"
                [ "$1" ] && echo $1
            #fi
        fi
    done
}

getavailablepv()
{
    for i in "$(pvs -o pv_name,pv_size --noheading)"; do
        #if [ "$(echo $i | grep dm-)" ]; then
            #getsymlink="$(readlink $(echo $i | sed -e 's#\ .*$##g'))"
            #correctdevice="$(echo $getsymlink | sed -e 's#\.\.#/dev#g')"
            #echo "$i" | sed -e "s#.*\ #$correctdevice\ \\n#g"
        #else
            echo "$i" | sed -e 's#$#\\n#'
        #fi
    done
}

#find volume groups that are not already full in use
findvg()
{
    for dev in $(vgs -o vg_name --noheading);do
        if ! [ "$(vgs -o vg_free --noheading --units m $dev | grep " 0M$")" ]; then
            echo "$dev"
            [ "$1" ] && echo $1
        fi
    done
}

getavailablevg()
{
    for i in $(vgs -o vg_name,vg_free --noheading --units m); do
        if ! [ $(echo $i | grep " 0M$") ]; then
            echo $i | sed -e 's#$#\\n#'
        fi
    done
}

# Creates volume group
_createvg()
{
    VGFINISH=""
    while [ "$VGFINISH" != "DONE" ]; do
        : >/tmp/.pvs
        VGDEVICE=""
        PVS=$(findpv _)
        # break if all devices are in use
        if [ "$PVS" = "" ]; then
            DIALOG --msgbox "No devices left for Volume Group creation." 0 0
            return 1
        fi
        # enter volume group name
        VGDEVICE=""
        while [ "${VGDEVICE}" = "" ]; do
            DIALOG --inputbox "Enter the Volume Group name:\nfoogroup\n<yourvolumegroupname>\n\n" 15 65 "foogroup" 2>$ANSWER || return 1
            VGDEVICE=$(cat $ANSWER)
            if [ "$(vgs -o vg_name --noheading 2>/dev/null | grep "^  $(echo $VGDEVICE)")" ]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical Volume Group names! Please enter another name." 8 65
                VGDEVICE=""
            fi
        done
        # show all devices with sizes
        DIALOG --msgbox "Physical Volumes:\n$(getavailablepv)\n\nPhysical Volumes that are not shown in next dialog, are already in use!" 0 0
        # select the first device to use, no missing option available!
        PVNUMBER=1
        DIALOG --menu "Select Physical Volume $PVNUMBER for $VGDEVICE" 21 50 13 $PVS 2>$ANSWER || return 1
        PV=$(cat $ANSWER)
        echo "$PV" >>/tmp/.pvs
        while [ "$PVS" != "DONE" ]; do
            PVNUMBER=$(($PVNUMBER + 1))
            # clean loop from used partition and options
            PVS="$(echo $PVS | sed -e "s#${PV}\ _##g")"
            # add more devices
            DIALOG --menu "Select additional Physical Volume $PVNUMBER for $VGDEVICE" 21 50 13 $PVS DONE _ 2>$ANSWER || return 1
            PV=$(cat $ANSWER)
            [ "$PV" = "DONE" ] && break
            echo "$PV" >>/tmp/.pvs
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create Volume Group like this?\n\n$VGDEVICE\n\nPhysical Volumes:\n$(cat /tmp/.pvs | sed -e 's#$#\\n#g')" 0 0 && VGFINISH="DONE"
    done
    DIALOG --infobox "Creating Volume Group $VGDEVICE..." 0 0
    PV="$(echo -n $(cat /tmp/.pvs))"
    vgcreate $VGDEVICE $PV >$LOG 2>&1
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error creating Volume Group $VGDEVICE (see $LOG for details)." 0 0
        return 1
    fi
}

# Creates logical volume
_createlv()
{
    LVFINISH=""
    while [ "$LVFINISH" != "DONE" ]; do
        LVDEVICE=""
        LV_SIZE_SET=""
        LVS=$(findvg _)
        # break if all devices are in use
        if [ "$LVS" = "" ]; then
            DIALOG --msgbox "No Volume Groups with free space available for Logical Volume creation." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "Volume Groups:\n$(getavailablevg)\n\nVolume Groups that are not shown, are already 100% in use!" 0 0
        DIALOG --menu "Select Volume Group" 21 50 13 $LVS 2>$ANSWER || return 1
        LV=$(cat $ANSWER)
        # enter logical volume name
        LVDEVICE=""
        while [ "${LVDEVICE}" = "" ]; do
            DIALOG --inputbox "Enter the Logical Volume name:\nfooname\n<yourvolumename>\n\n" 15 65 "fooname" 2>$ANSWER || return 1
            LVDEVICE=$(cat $ANSWER)
            if [ "$(lvs -o lv_name,vg_name --noheading 2>/dev/null | grep " $(echo $LVDEVICE) $(echo $LV)"$)" ]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical Logical Volume names! Please enter another name." 8 65
                LVDEVICE=""
            fi
        done
        while [ "$LV_SIZE_SET" = "" ]; do
            LV_ALL=""
            DIALOG --inputbox "Enter the size (MB) of your Logical Volume,\nMinimum value is > 0.\n\nVolume space left: $(vgs -o vg_free --noheading --units m $LV)B\n\nIf you enter no value, all free space left will be used." 10 65 "" 2>$ANSWER || return 1
                LV_SIZE=$(cat $ANSWER)
                if [ "$LV_SIZE" = "" ]; then
                    DIALOG --yesno "Would you like to create Logical Volume with free space left?" 0 0 && LV_ALL="1"
                fi
                if [ "$LV_SIZE" = "0" ]; then
                    DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
                else
                    if [ "$LV_SIZE" -ge "$(vgs -o vg_free --noheading --units m | sed -e 's#M##g')" ]; then
                        DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                    else
                        LV_SIZE_SET=1
                    fi
                fi
        done
        #Contiguous doesn't work with +100%FREE
        LV_CONTIGUOUS=""
        [ "$LV_ALL" = "" ] && DIALOG --defaultno --yesno "Would you like to create Logical Volume as a contiguous partition, that means that your space doesn't get partitioned over one or more disks nor over non-contiguous physical extents.\n(usefull for swap space etc.)?" 0 0 && LV_CONTIGUOUS="1"
        if [ "$LV_CONTIGUOUS" = "1" ]; then
            CONTIGUOUS=yes
            LV_EXTRA="-C y"
        else
            CONTIGUOUS=no
            LV_EXTRA=""
        fi
        [ "$LV_SIZE" = "" ] && LV_SIZE="All free space left"
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to create Logical Volume $LVDEVICE like this?\nVolume Group:\n$LV\nVolume Size:\n$LV_SIZE\nContiguous Volume:\n$CONTIGUOUS" 0 0 && LVFINISH="DONE"
    done
    DIALOG --infobox "Creating Logical Volume $LVDEVICE..." 0 0
    if [ "$LV_ALL" = "1" ]; then
        lvcreate $LV_EXTRA -l +100%FREE $LV -n $LVDEVICE >$LOG 2>&1
    else
        lvcreate $LV_EXTRA -L $LV_SIZE\M $LV -n $LVDEVICE >$LOG 2>&1
    fi
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error creating Logical Volume $LVDEVICE (see $LOG for details)." 0 0
        return 1
    fi
}

# help for luks
_helpluks()
{
DIALOG --msgbox "LUKS ENCRYPTION SUMMARY:\n
-----------------------------\n\n
Encryption is useful for two (related) reasons.\n
Firstly, it prevents anyone with physical access to your computer,\n
and your hard drive in particular, from getting the data from it\n
(unless they have your passphrase/key).\n
Secondly, it allows you to wipe the data on your hard drive with\n
far more confidence in the event of you selling or discarding\n
your drive.\n
Basically, it supplements the access control mechanisms of the operating\n
system (like file permissions) by making it harder to bypass the operating\n
system by inserting a boot CD, for example. Encrypting the root partition\n
prevents anyone from using this method to insert viruses or trojans onto\n
your computer.\n\n
ATTENTION:\n
Having encrypted partitions does not protect you from all possible\n
attacks. The encryption is only as good as your key management, and there\n
are other ways to break into computers, while they are running." 0 0
}

# create luks device
_luks()
{
    LUKSFINISH=""
    while [ "$LUKSFINISH" != "DONE" ]; do
        #PARTS=$(finddisks _)
        PARTS="$(findpartitions _)"
        ALREADYINUSE=""
        # skip already encrypted devices, device mapper!
        for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
            [ "$(cryptsetup status $devpath)" ] && ALREADYINUSE="$ALREADYINUSE /dev/mapper/$devpath"
        done
        # skip already encrypted devices, device mapper with encrypted parts!
        for devpath in $(pvs -o pv_name --noheading); do
	     if [ "$(echo $devpath | grep dm-)" ]; then
                if [ "$(cryptsetup status $(basename $devpath))" ]; then
                   killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                   ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
                fi
             fi
             # remove hidden crypt by md device
             if [ "$(echo $devpath | grep /dev/md)" ]; then
                 mdcheck="$(echo $devpath | sed -e 's#/dev/##g')"
                 if ! [ "$(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null)" = "" ]; then
                     for k in $(find /sys/block/$mdcheck/slaves/ -name 'dm*'); do
                         if [ "$(cryptsetup status $(cat $k/dm/name))" ]; then
                             killvolumegroup="$(echo $(pvs -o vg_name --noheading $devpath))"
                             ALREADYINUSE="$ALREADYINUSE $(ls /dev/mapper/$killvolumegroup-*)"
                         fi
                     done
                 fi
             fi
        done
        # skip md devices, which already has encrypted devices!
        for i in $PARTS; do
            mdcheck="$(echo $i | sed -e 's#/dev/##g')"
            if ! [ "$(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null)" = "" ]; then
                for k in $(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null); do
                    [ "$(cryptsetup status $(cat $k/dm/name))"  ] && ALREADYINUSE="$ALREADYINUSE $i"
                    # check lvm devices if encryption was used!
                    if [ "$(lvs /dev/mapper/$(cat $k/dm/name) 2>/dev/null)" ]; then
                        for devpath in $ALREADYINUSE; do
                            [ "$(echo $devpath | grep "/dev/mapper/$(cat $k/dm/name)"$)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                        done
                    fi
                done
            fi
        done
        # skip md partition devices, which already has encrypted devices!
        for i in $PARTS; do
            mdcheck="$(echo $i | grep /dev/md_d | sed -e 's#p.*##g' -e 's#/dev/##g')"
            if [ "$(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null)" != "" -a "$mdcheck" != "" ]; then
                for k in $(find /sys/block/$mdcheck/slaves/ -name 'dm*' 2>/dev/null); do
                    [ "$(cryptsetup status $(cat $k/dm/name))" ] && ALREADYINUSE="$ALREADYINUSE $i"
                    # check lvm devices if encryption was used!
                    if [ "$(lvs /dev/mapper/$(cat $k/dm/name) 2>/dev/null)" ]; then
                        for devpath in $ALREADYINUSE; do
                            [ "$(echo $devpath | grep "/dev/mapper/$(cat $k/dm/name)"$)" ] && ALREADYINUSE="$ALREADYINUSE $i"
                        done
                    fi
                done
            fi
        done
        for i in $ALREADYINUSE; do
            PARTS=$(echo $PARTS | sed -e "s#$i\ _##g")
        done
        # break if all devices are in use
        if [ "$PARTS" = "" ]; then
            DIALOG --msgbox "No devices left for luks encryption." 0 0
            return 1
        fi
        # show all devices with sizes
        DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
        DIALOG --menu "Select device for luks encryption" 21 50 13 $PARTS 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
        # enter luks name
        LUKSDEVICE=""
        while [ "${LUKSDEVICE}" = "" ]; do
            DIALOG --inputbox "Enter the name for luks encrypt device:\nfooname\n<yourname>\n\n" 15 65 "fooname" 2>$ANSWER || return 1
            LUKSDEVICE=$(cat $ANSWER)
            if ! [ "$(cryptsetup status $LUKSDEVICE | grep inactive)" ]; then
                DIALOG --msgbox "ERROR: You have defined 2 identical luks encryption device names! Please enter another name." 8 65
                LUKSDEVICE=""
            fi
        done
        # final step ask if everything is ok?
        DIALOG --yesno "Would you like to encrypt luks device below?\nName:$LUKSDEVICE\nDevice:$PART\n" 0 0 && LUKSFINISH="DONE"
    done
    LUKSPASSPHRASE=""
    while [ "${LUKSPASSPHRASE}" = "" ]; do
        DIALOG --insecure --passwordbox "Enter passphrase:" 0 0 2>$ANSWER || return 1
        LUKSPASS=$(cat $ANSWER)
        DIALOG --insecure --passwordbox "Retype passphrase:" 0 0 2>$ANSWER || return 1
        LUKSPASS2=$(cat $ANSWER)
        if [ "$LUKSPASS" = "$LUKSPASS2" ]; then
            LUKSPASSPHRASE=$LUKSPASS
            echo $LUKSPASSPHRASE > /tmp/.passphrase
            LUKSPASSPHRASE=/tmp/.passphrase
        else
             DIALOG --msgbox "Passphrases didn't match, please enter again." 0 0
        fi
    done
    DIALOG --infobox "Encrypting $PART..." 0 0
    cryptsetup -c aes-xts-plain -s 512 luksFormat $PART >$LOG <$LUKSPASSPHRASE
    DIALOG --infobox "Opening encrypted $PART..." 0 0
    cryptsetup luksOpen $PART $LUKSDEVICE >$LOG <$LUKSPASSPHRASE  
    LUKSPASSPHRASE="$(cat $LUKSPASSPHRASE)"
    echo $LUKSDEVICE $PART $LUKSPASSPHRASE >> /tmp/.crypttab
    rm /tmp/.passphrase
}

autoprepare() {
    # check on encrypted devices, else weird things can happen!
    _stopluks
    # check on raid devices, else weird things can happen during partitioning!
    _stopmd
    # check on lvm devices, else weird things can happen during partitioning!
    _stoplvm
    DISCS=$(findautoprepare)
    if [ $(echo $DISCS | wc -w) -gt 1 ]; then
        DIALOG --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
        DIALOG --menu "Select the hard drive to use" 14 55 7 $(findautoprepare _) 2>$ANSWER || return 1
        DISC=$(cat $ANSWER)
    else
        DISC=$DISCS
    fi
    SET_DEFAULTFS=""
    BOOT_PART_SET=""
    SWAP_PART_SET=""
    ROOT_PART_SET=""
    CHOSEN_FS=""
    # get just the disk size in 1000*1000 MB
    DISC_SIZE=$(echo $(($(expr 512 '*' $(cat /sys/block/$(basename $DISC)/size))/1000000)))
    while [ "$SET_DEFAULTFS" = "" ]; do
        FSOPTS=""
        [ "$(which mkfs.ext2 2>/dev/null)" ] && FSOPTS="$FSOPTS ext2 Ext2"
        [ "$(which mkfs.ext3 2>/dev/null)" ] && FSOPTS="$FSOPTS ext3 Ext3"
        [ "$(which mkfs.ext4 2>/dev/null)" ] && FSOPTS="$FSOPTS ext4 Ext4"
        [ "$(which mkreiserfs 2>/dev/null)" ] && FSOPTS="$FSOPTS reiserfs Reiser3"
        [ "$(which mkfs.xfs 2>/dev/null)" ]   && FSOPTS="$FSOPTS xfs XFS"
        [ "$(which mkfs.jfs 2>/dev/null)" ]   && FSOPTS="$FSOPTS jfs JFS"
        while [ "$BOOT_PART_SET" = "" ]; do
            DIALOG --inputbox "Enter the size (MB) of your /boot partition,\nMinimum value is 16.\n\nDisk space left: $DISC_SIZE MB" 10 65 "32" 2>$ANSWER || return 1
            BOOT_PART_SIZE="$(cat $ANSWER)"
            if [ "$BOOT_PART_SIZE" = "" ]; then
                DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
            else
                if [ "$BOOT_PART_SIZE" -ge "$DISC_SIZE" -o "$BOOT_PART_SIZE" -lt "16" -o "$SBOOT_PART_SIZE" = "$DISC_SIZE" ]; then
                    DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                else
                    BOOT_PART_SET=1
                fi
            fi
        done
        DISC_SIZE=$(($DISC_SIZE-$BOOT_PART_SIZE))
        while [ "$SWAP_PART_SET" = "" ]; do
            DIALOG --inputbox "Enter the size (MB) of your swap partition,\nMinimum value is > 0.\n\nDisk space left: $DISC_SIZE MB" 10 65 "256" 2>$ANSWER || return 1
            SWAP_PART_SIZE=$(cat $ANSWER)
            if [ "$SWAP_PART_SIZE" = "" -o  "$SWAP_PART_SIZE" = "0" ]; then
                DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
            else
                if [ "$SWAP_PART_SIZE" -ge "$DISC_SIZE" ]; then
                    DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                else
                    SWAP_PART_SET=1
                fi
            fi
        done
        DISC_SIZE=$(($DISC_SIZE-$SWAP_PART_SIZE))
        while [ "$ROOT_PART_SET" = "" ]; do
        DIALOG --inputbox "Enter the size (MB) of your / partition,\nthe /home partition will use the remaining space.\n\nDisk space left:  $DISC_SIZE MB" 10 65 "7500" 2>$ANSWER || return 1
        ROOT_PART_SIZE=$(cat $ANSWER)
            if [ "$ROOT_PART_SIZE" = "" -o "$ROOT_PART_SIZE" = "0" ]; then
                DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
            else
                if [ "$ROOT_PART_SIZE" -ge "$DISC_SIZE" ]; then
                    DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
                else
                    DIALOG --yesno "$(($DISC_SIZE-$ROOT_PART_SIZE)) MB will be used for your /home partition. Is this OK?" 0 0 && ROOT_PART_SET=1
                fi
            fi
        done
        while [ "$CHOSEN_FS" = "" ]; do
            DIALOG --menu "Select a filesystem for / and /home:" 13 45 6 $FSOPTS 2>$ANSWER || return 1
            FSTYPE=$(cat $ANSWER)
            DIALOG --yesno "$FSTYPE will be used for / and /home. Is this OK?" 0 0 && CHOSEN_FS=1
        done
        SET_DEFAULTFS=1
    done
    REAL_DEFAULTFS=$(echo $DEFAULTFS | sed -e "s|/:7500:ext3|/:$ROOT_PART_SIZE:$FSTYPE|g" -e "s|/home:\*:ext3|/home:\*:$FSTYPE|g" -e "s|swap:256|swap:$SWAP_PART_SIZE|g" -e "s|/boot:32|/boot:$BOOT_PART_SIZE|g")
    DIALOG --defaultno --yesno "$DISC will be COMPLETELY ERASED!  Are you absolutely sure?" 0 0 \
    || return 1
    DEVICE=$DISC
    FSSPECS=$(echo $DEFAULTFS | sed -e "s|/:7500:ext3|/:$ROOT_PART_SIZE:$FSTYPE|g" -e "s|/home:\*:ext3|/home:\*:$FSTYPE|g" -e "s|swap:256|swap:$SWAP_PART_SIZE|g" -e "s|/boot:32|/boot:$BOOT_PART_SIZE|g")
    sfdisk_input=""

    if [ "$S_MKFS" = "1" ]; then
        DIALOG --msgbox "You have already prepared your filesystems manually" 0 0
        return 0
    fi

    # validate DEVICE
    if [ ! -b "$DEVICE" ]; then
      DIALOG --msgbox "Device '$DEVICE' is not valid" 0 0
      return 1
    fi

    # validate DEST
    if [ ! -d "$DESTDIR" ]; then
        DIALOG --msgbox "Destination directory '$DESTDIR' is not valid" 0 0
        return 1
    fi

    # / required
    if [ $(echo $FSSPECS | grep '/:' | wc -l) -ne 1 ]; then
        DIALOG --msgbox "Need exactly one root partition" 0 0
        return 1
    fi

    dev=$DEVICE
    # we assume a /dev/hdX format (or /dev/sdX)
    PART_ROOT="${DEVICE}3"

    rm -f /tmp/.fstab

    # disable swap and all mounted partitions, umount / last!
    _umountall

    # setup input var for sfdisk
    for fsspec in $FSSPECS; do
        fssize=$(echo $fsspec | tr -d ' ' | cut -f2 -d:)
        if [ "$fssize" = "*" ]; then
                fssize_spec=';'
        else
                fssize_spec=",$fssize"
        fi
        fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
        if [ "$fstype" = "swap" ]; then
                fstype_spec=",S"
        else
                fstype_spec=","
        fi
        bootflag=$(echo $fsspec | tr -d ' ' | cut -f4 -d:)
        if [ "$bootflag" = "+" ]; then
            bootflag_spec=",*"
        else
            bootflag_spec=""
        fi
        sfdisk_input="${sfdisk_input}${fssize_spec}${fstype_spec}${bootflag_spec}\n"
    done
    sfdisk_input=$(printf "$sfdisk_input")

    # invoke sfdisk
    printk off
    DIALOG --infobox "Partitioning $DEVICE" 0 0
    # clean partitiontable to avoid issues!
    dd if=/dev/zero of=$DEVICE bs=512 count=1 >/dev/null 2>&1
    sfdisk $DEVICE -uM >$LOG 2>&1 <<EOF
$sfdisk_input
EOF
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error partitioning $DEVICE (see $LOG for details)" 0 0
        printk on
        return 1
    fi
    printk on

    # need to mount root first, then do it again for the others
    part=1
    for fsspec in $FSSPECS; do
        mountpoint=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
        fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
        if echo $mountpoint | tr -d ' ' | grep '^/$' 2>&1 >/dev/null; then
            _mkfs yes ${DEVICE}${part} "$fstype" "$DESTDIR" "$mountpoint" || return 1
        fi
        part=$(($part + 1))
    done

    # make other filesystems
    part=1
    for fsspec in $FSSPECS; do
        mountpoint=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
        fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
        if [ $(echo $mountpoint | tr -d ' ' | grep '^/$' | wc -l) -eq 0 ]; then
            _mkfs yes ${DEVICE}${part} "$fstype" "$DESTDIR" "$mountpoint" || return 1
        fi
        part=$(($part + 1))
    done

    DIALOG --msgbox "Auto-prepare was successful" 0 0
    S_MKFSAUTO=1
}

partition() {
    if [ "$S_MKFSAUTO" = "1" ]; then
        DIALOG --msgbox "You have already prepared your filesystems with Auto-prepare" 0 0
        return 0
    fi
    # disable swap and all mounted partitions, umount / last!
    _umountall
    # check on encrypted devices, else weird things can happen!
    _stopluks
    # check on raid devices, else weird things can happen during partitioning!
    _stopmd
    # check on lvm devices, else weird things can happen during partitioning!
    _stoplvm
    # update dmraid
    _dmraid_update
    # Select disk to partition
    DISCS=$(finddisks _)
    DISCS="$DISCS OTHER _ DONE +"
    DIALOG --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
    DISC=""
    while true; do
        # Prompt the user with a list of known disks
        DIALOG --menu "Select the disk you want to partition\n(select DONE when finished)" 14 55 7 $DISCS 2>$ANSWER || return 1
        DISC=$(cat $ANSWER)
        if [ "$DISC" = "OTHER" ]; then
            DIALOG --inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>$ANSWER || DISC=""
            DISC=$(cat $ANSWER)
        fi
        # Leave our loop if the user is done partitioning
        [ "$DISC" = "DONE" ] && break
        if ! [ "$DISC" = "" ]; then
            # Partition disc
            DIALOG --msgbox "Now you'll be put into the cfdisk program where you can partition your hard drive. You should make a swap partition and as many data partitions as you will need.  NOTE: cfdisk may tell you to reboot after creating partitions.  If you need to reboot, just re-enter this install program, skip this step and go on to step 2." 18 70
            cfdisk $DISC
        fi
    done
    # update dmraid
    _dmraid_update
    NEXTITEM="3"
    S_PART=1
}

mountpoints() {
    if [ "$S_MKFSAUTO" = "1" ]; then
        DIALOG --msgbox "You have already prepared your filesystems with Auto-prepare" 0 0
        return 0
    fi
    while [ "$PARTFINISH" != "DONE" ]; do
    : >/tmp/.fstab
    : >/tmp/.parts
    FSOPTS=""
    [ "$(which mkfs.ext2 2>/dev/null)" ] && FSOPTS="$FSOPTS ext2 Ext2"
    [ "$(which mkfs.ext3 2>/dev/null)" ] && FSOPTS="$FSOPTS ext3 Ext3"
    [ "$(which mkfs.ext4 2>/dev/null)" ] && FSOPTS="$FSOPTS ext4 Ext4"
    [ "$(which mkreiserfs 2>/dev/null)" ] && FSOPTS="$FSOPTS reiserfs Reiser3"
    [ "$(which mkfs.xfs 2>/dev/null)" ]   && FSOPTS="$FSOPTS xfs XFS"
    [ "$(which mkfs.jfs 2>/dev/null)" ]   && FSOPTS="$FSOPTS jfs JFS"
    [ "$(which mkfs.ntfs 2>/dev/null)" ]   && FSOPTS="$FSOPTS ntfs-3g NTFS"
    [ "$(which mkfs.vfat 2>/dev/null)" ]   && FSOPTS="$FSOPTS vfat VFAT"
    #
    # Select mountpoints
    #
    DIALOG --msgbox "Available partitions:\n\n$(_getavailpartitions)\n" 0 0
    PARTS=$(findpartitions _)
    DIALOG --menu "Select the partition to use as swap" 21 50 13 NONE - $PARTS 2>$ANSWER || return 1
    PART=$(cat $ANSWER)
    PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
    if [ "$PART" != "NONE" ]; then
        DOMKFS="no"
        DIALOG --yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" 0 0 && DOMKFS="yes"
        echo "$PART:swap:swap:$DOMKFS" >>/tmp/.parts
    fi
    DIALOG --menu "Select the partition to mount as /" 21 50 13 $PARTS 2>$ANSWER || return 1
    PART=$(cat $ANSWER)
    PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
    PART_ROOT=$PART
    # Select root filesystem type
    DIALOG --menu "Select a filesystem for $PART" 21 50 13 $FSOPTS 2>$ANSWER || return 1
    FSTYPE=$(cat $ANSWER)
    DOMKFS="no"
    DIALOG --yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" 0 0 && DOMKFS="yes"
    echo "$PART:$FSTYPE:/:$DOMKFS" >>/tmp/.parts

    #
    # Additional partitions
    #
    DIALOG --menu "Select any additional partitions to mount under your new root (select DONE when finished)" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
    PART=$(cat $ANSWER)
    while [ "$PART" != "DONE" ]; do
        PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
        # Select a filesystem type
        DIALOG --menu "Select a filesystem for $PART" 21 50 13 $FSOPTS 2>$ANSWER || return 1
        FSTYPE=$(cat $ANSWER)
        MP=""
        while [ "${MP}" = "" ]; do
            DIALOG --inputbox "Enter the mountpoint for $PART" 8 65 "/boot" 2>$ANSWER || return 1
            MP=$(cat $ANSWER)
            if grep ":$MP:" /tmp/.parts; then
                DIALOG --msgbox "ERROR: You have defined 2 identical mountpoints! Please select another mountpoint." 8 65
                MP=""
            fi
        done
        DOMKFS="no"
        DIALOG --yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" 0 0 && DOMKFS="yes"
        echo "$PART:$FSTYPE:$MP:$DOMKFS" >>/tmp/.parts
        DIALOG --menu "Select any additional partitions to mount under your new root" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
    done
    DIALOG --yesno "Would you like to create and mount the filesytems like this?\n\nSyntax\n------\nDEVICE:TYPE:MOUNTPOINT:FORMAT\n\n$(for i in $(cat /tmp/.parts); do echo "$i\n";done)" 0 0 && PARTFINISH="DONE"
    done
    # disable swap and all mounted partitions
    _umountall
    for line in $(cat /tmp/.parts); do
        PART=$(echo $line | cut -d: -f 1)
        FSTYPE=$(echo $line | cut -d: -f 2)
        MP=$(echo $line | cut -d: -f 3)
        DOMKFS=$(echo $line | cut -d: -f 4)
        if [ "$DOMKFS" = "yes" ]; then
            if [ "$FSTYPE" = "swap" ]; then
                DIALOG --infobox "Creating and activating swapspace on $PART" 0 0
            else
                DIALOG --infobox "Creating $FSTYPE on $PART, mounting to ${DESTDIR}${MP}" 0 0
            fi
            _mkfs yes $PART $FSTYPE $DESTDIR $MP || return 1
        else
            if [ "$FSTYPE" = "swap" ]; then
                DIALOG --infobox "Activating swapspace on $PART" 0 0
            else
                DIALOG --infobox "Mounting $FSTYPE on $PART to ${DESTDIR}${MP}" 0 0
            fi
            _mkfs no $PART $FSTYPE $DESTDIR $MP || return 1
        fi
        sleep 1
    done

    DIALOG --msgbox "Partitions were successfully mounted." 0 0
    NEXTITEM="5"
    S_MKFS=1
}

getsource() {
    S_SRC=0
    if [ "$MODE" = "media" ]; then
        get_media
        #last fallback, if autodetection fails!
        manual_media
    fi

    if [ "$MODE" = "ftp" ]; then
        #in order to cache packages from media check on it first!
        get_media
        select_mirror
        NEXTITEM="2"
    fi
    S_SRC=1
}

# select_mirror()
# Prompt user for preferred mirror and set $SYNC_URL
#
# args: none
# returns: nothing
select_mirror() {
    DIALOG --msgbox "Keep in mind ftp.archlinux.org is throttled.\nPlease select another mirror to get full download speed." 10 65
    # FIXME: this regex doesn't honor commenting
    MIRRORS=$(egrep -o '((ftp)|(http))://[^/]*' "${MIRRORLIST}" | sed 's|$| _|g')
    DIALOG --menu "Select an FTP/HTTP mirror" 14 55 7 \
        $MIRRORS \
        "Custom" "_" 2>$ANSWER || return 1
    local _server=$(cat $ANSWER)
    if [ "${_server}" = "Custom" ]; then
        DIALOG --inputbox "Enter the full URL to core repo." 8 65 \
            "ftp://ftp.archlinux.org/core/os/$(uname -m)" 2>$ANSWER || return 1
            SYNC_URL=$(cat $ANSWER)
    else
        # Form the full URL for our mirror by grepping for the server name in
        # our mirrorlist and pulling the full URL out. Substitute 'core' in
        # for the repository name, and ensure that if it was listed twice we
        # only return one line for the mirror.
        SYNC_URL=$(egrep -o "${_server}.*" "${MIRRORLIST}" | head -n1)
    fi
    echo "Using mirror: $SYNC_URL" >$LOG
}

# pacman_conf()
# creates temporary pacman.conf file
pacman_conf() {
    if [ "$MODE" = "media" ]; then
        local serverurl="${FILE_URL}"
    elif [ "$MODE" = "ftp" ]; then
        local serverurl="${SYNC_URL}"
    fi
    # Setup a pacman.conf in /tmp
    cat << EOF > /tmp/pacman.conf
[options]
CacheDir = ${DESTDIR}/var/cache/pacman/pkg
CacheDir = /src/core-$(uname -m)/pkg
CacheDir = /src/core-any/pkg

[core]
Server = ${serverurl}
EOF
}

# pacman_conf_extra()
# adds extra repository for ftp installation mode
prepare_pacman_extra() {
    local serverurl="${SYNC_URL}"
    # Setup a pacman.conf in /tmp
    echo "[extra]" >> /tmp/pacman.conf
    echo "Server =  ${serverurl}" >> /tmp/pacman.conf
}

# configures pacman and syncs for the first time on destination system
# params: none
# returns: 1 on error
prepare_pacman() {
    # Set up the necessary directories for pacman use
    [ ! -d "${DESTDIR}/var/cache/pacman/pkg" ] && mkdir -m 755 -p "${DESTDIR}/var/cache/pacman/pkg"
    [ ! -d "${DESTDIR}/var/lib/pacman" ] && mkdir -m 755 -p "${DESTDIR}/var/lib/pacman"

    DIALOG --infobox "Refreshing package database..." 6 45
    $PACMAN -Sy >$LOG 2>&1 || return 1
    return 0
}

# select_packages()
# prompts the user to select packages to install
#
# params: none
# returns: 1 on error
select_packages() {
    if ! [ "$S_SRC" = "1" ]; then
        DIALOG --msgbox "Error:\nYou must select Source first." 0 0
        return 1
    fi
    # set up our install location if necessary and sync up
    # so we can get package lists
    pacman_conf
    prepare_pacman
    if [ $? -ne 0 ]; then
        DIALOG --msgbox "Pacman preparation failed! Check $LOG for errors." 6 60
        return 1
    fi
    # Archboot setup media Mode uses packages.txt!
    if [ "$MODE" = "media" ]; then
        DIALOG --msgbox "Package selection is split into two stages.  First you will select package categories that contain packages you may be interested in.  Then you will be presented with a full list of packages in your selected categories, allowing you to fine-tune your selection.\n\nNOTE: It is recommended that you install the BASE category from this setup, SUPPORT contains additional useful packages for networking and filesystems, DEVEL contains software building tools." 18 70
        PKGS="/src/core-$(uname -m)/pkg/packages.txt"
        if ! [ -f /tmp/.pkgcategory ]; then
            CHKLIST="base ^ ON"
            for category in $(cat $PKGS | sed 's|/.*$||g' | uniq | grep -v base | grep -v kernels); do
                CHKLIST="$CHKLIST $category - OFF"
            done
        else
            CHKLIST=
            for i in $(cat /tmp/.pkgcategory | sed 's|\"||g'); do
                CHKLIST="$CHKLIST $i ^ ON"
            done
            for category in $(cat $PKGS | sed 's|/.*$||g' | uniq | grep -v kernels); do
                grep $category /tmp/.pkgcategory >/dev/null 2>&1 || CHKLIST="$CHKLIST $category - OFF"
            done
        fi
        DIALOG --checklist "Select Package Categories" 19 55 12 $CHKLIST 2>/tmp/.pkgcategory || return 1
        SELECTALL="no"
        DIALOG --yesno "Select all packages by default?" 0 0 && SELECTALL="yes"
        CHKLIST=
        for category in $(cat /tmp/.pkgcategory | sed 's|"||g'); do
            tag="OFF"
            if [ "$SELECTALL" = "yes" ]; then
                tag="ON"
            fi
            list=$(cat $PKGS | grep "$category/" | sed 's|^[a-z0-9-]*/||g' | sed "s|.pkg.tar.gz$| ($category) $tag|g" | sort)
            CHKLIST="$CHKLIST $list"
            tag="OFF"
        done
        DIALOG --checklist "Select Packages to install.  Use SPACE to select." 19 60 12 $CHKLIST 2>/tmp/.pkglist || return 1
        # fix pacman list!
        PACKAGES=
        sed -i -e 's/-i686//g' -e 's/-x86_64//g' -e 's/-any//g' -e 's/"//g' /tmp/.pkglist
        for pkg in $(cat /tmp/.pkglist); do
            pkgname=${pkg%-*-*}
            PACKAGES="$PACKAGES $pkgname"
        done
    # Use default ftp install routine from arch livecd
    else
        # if selection has been done before, warn about loss of input
        # and let the user exit gracefully
        if [ $S_SELECT -ne 0 ]; then
            DIALOG --yesno "WARNING: Running this stage again will result in the loss of previous package selections.\n\nDo you wish to continue?" 10 50 || return 1
        fi
        DIALOG --msgbox "Package selection is split into two stages.  First you will select package categories that contain packages you may be interested in.  Then you will be presented with a full list of packages for each category, allowing you to fine-tune.\n\n" 15 70
        # show group listing for group selection
        local _catlist="base ^ ON"
        for i in $($PACMAN -Sg | sed "s/^base$/ /g"); do
            _catlist="${_catlist} ${i} - OFF"
        done

        DIALOG --checklist "Select Package Categories\nDO NOT deselect BASE unless you know what you're doing!" 19 55 12 $_catlist 2>$ANSWER || return 1
        _catlist="$(cat $ANSWER)"

        # assemble a list of packages with groups, marking pre-selected ones
        # <package> <group> <selected>
        local _pkgtmp="$($PACMAN -Sl core | awk '{print $2}')"
        local _pkglist=''

        $PACMAN -Si $_pkgtmp | \
        awk '/^Name/{ printf("%s ",$3) } /^Group/{ print $3 }' > $ANSWER
        while read pkgname pkgcat; do

            # check if this package is in a selected group
            # slightly ugly but sorting later requires newlines in the variable
            if [ "${_catlist/"\"$pkgcat\""/XXXX}" != "${_catlist}" ]; then
                _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} ON")"
            else
                _pkglist="$(echo -e "${_pkglist}\n${pkgname} ${pkgcat} OFF")"
            fi
        done < $ANSWER

        # sort by category
        _pkglist="$(echo "$_pkglist" | sort -f -k 2)"

        DIALOG  --separate-output --checklist "Select Packages To Install." 19 60 12 $_pkglist 2>$ANSWER || return 1
        PACKAGES="$(cat $ANSWER)"
        pacman_conf_extra
        prepare_pacman
    fi
    # Add packages which are not in core repository
    [ "$(grep -w nvidia-kms /proc/cmdline)" ] && ! [ "$(grep -w nouveau-drm $PACKAGES)" ] && PACKAGES="$PACKAGES nouveau-drm nouveau-firmware"
    [ "$(grep -w uvesafb /proc/cmdline)" ] && ! [ "$(grep -w v86d $PACKAGES)" ] && PACKAGES="$PACKAGES v86d"
    [ "$(blkid -c /dev/null -o value -s TYPE | grep ntfs)" ] && ! [ "$(grep -w ntfs-3g $PACKAGES)" ] && PACKAGES="$PACKAGES ntfs-3g"
    [ -e /var/state/dhcp/dhclient.leases ] && ! [ "$(grep -w dhclient $PACKAGES)" ] && PACKAGES="$PACKAGES dhclient"
    # Only install the booted kernel image!
    PACKAGES="$(echo $PACKAGES | sed -e "s#\ kernel26\ # #g" -e  "s#\ kernel26-lts\ # #g")"
    PACKAGES="$KERNELPKG $PACKAGES"
    NEXTITEM="5"
    S_SELECT=1
}


# installpkg()
# performs package installation to the target system
#
installpkg() {
    if ! [ "$S_SRC" = "1" ]; then
        DIALOG --msgbox "Error:\nYou must select Source first." 0 0
        return 1
    fi
    if [ "$MODE" = "media" ]; then
        if [ ! -f /tmp/.pkglist -o "$S_SELECT" != "1" ]; then
            DIALOG --msgbox "You must select packages first." 0 0
            return 1
        fi
    else
        if [ "$S_SELECT" != "1" ]; then
            DIALOG --msgbox "You must select packages first." 0 0
            return 1
        fi
    fi
    if [ "$S_MKFS" != "1" -a "$S_MKFSAUTO" != "1" ]; then
        getdest
    fi

    DIALOG --msgbox "Package installation will begin now.  You can watch the output in the progress window. Please be patient." 0 0

    # create chroot environment on target system
    # code straight from mkarchroot
    chroot_mount

    # execute pacman in a subshell so we can follow its progress
    # pacman output goes /tmp/pacman.log
    # /tmp/setup-pacman-running acts as a lockfile
    ( \
        echo "Installing Packages..." >/tmp/pacman.log ; \
        echo >>/tmp/pacman.log ; \
        touch /tmp/setup-pacman-running ; \
        $PACMAN -S $PACKAGES 2>&1 >> /tmp/pacman.log ; \
        echo $? > /tmp/.pacman-retcode ; \
        if [ $(cat /tmp/.pacman-retcode) -ne 0 ]; then
            echo -e "\nPackage Installation FAILED." >>/tmp/pacman.log
        else
            echo -e "\nPackage Installation Complete." >>/tmp/pacman.log
        fi
        rm /tmp/setup-pacman-running
    ) &

    # display pacman output while it's running
    sleep 2
    dialog --backtitle "$TITLE" --title " Installing... Please Wait " \
        --no-kill --tailboxbg "/tmp/pacman.log" 18 70 2>$ANSWER
    while [ -f /tmp/setup-pacman-running ]; do
        sleep 1
    done
    kill $(cat $ANSWER)

    # pacman finished, display scrollable output
    local _result=''
    if [ $(cat /tmp/.pacman-retcode) -ne 0 ]; then
        _result="Installation Failed (see errors below)"
    else
        _result="Installation Complete"
    fi
    rm /tmp/.pacman-retcode
    DIALOG --title "$_result" --exit-label "Continue" \
        --textbox "/tmp/pacman.log" 18 70 || return 1
    # ensure the disk is synced
    sync

    S_INSTALL=1
    NEXTITEM="6"
    # automagic time!
    # any automatic configuration should go here
    DIALOG --infobox "Writing base configuration..." 6 40
    auto_addons
    auto_fstab
    auto_mdadm
    auto_luks
    auto_locale
    # tear down the chroot environment
    chroot_umount
}

# add archboot addons if activated
auto_addons()
{
    if [ -d /tmp/packages ]; then
        DO_ADDON=""
        DIALOG --yesno "Would you like to install your addons packages to installed system?" 0 0 && DO_ADDON="yes"
        if [ "$DO_ADDON" = "yes" ] ; then
            DIALOG --infobox "Installing the addons packages..." 0 0
            $PACMAN -U /tmp/packages/*
        fi
    fi
}

# auto_fstab()
# preprocess fstab file
# comments out old fields and inserts new ones
# according to partitioning/formatting stage
#
auto_fstab(){
    # Modify fstab
    if [ "$S_MKFS" = "1" -o "$S_MKFSAUTO" = "1" ]; then
        if [ -f /tmp/.fstab ]; then
            # clean fstab first from /dev entries
            sed -i -e '/^\/dev/d' $DESTDIR/etc/fstab
            # clean /media from old floppy,cd,dvd entries
            rm -r $DESTDIR/media/cd*
            rm -r $DESTDIR/media/dvd*
            rm -r $DESTDIR/media/fl*
            # add floppy,cd and dvd entries first
            for i in $(ls -d /dev/cdro* | grep -v "0"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    ro,user,noauto,unhide   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            for i in $(ls -d /dev/dvd* | grep -v "0"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    ro,user,noauto,unhide   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            for i in $(ls -d /dev/fd[0-9] | grep -v "[0-9][0-9][0-9]"); do
                k=$(echo $i | sed -e 's|/dev/||g')
                echo "$i /media/$k   auto    user,noauto   0      0" >>$DESTDIR/etc/fstab
            # create dirs in /media
                mkdir -p $DESTDIR/media/$k
            done
            sort /tmp/.fstab >>$DESTDIR/etc/fstab
        fi
    fi
}

# auto_locale()
# enable glibc locales from rc.conf and build initial locale DB
auto_locale()
{
    for i in $(grep "^LOCALE" ${DESTDIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
        sed -i -e "s/^#$i/$i/g" ${DESTDIR}/etc/locale.gen
    done
    DIALOG --infobox "Generating glibc base locales..." 4 40
    chroot ${DESTDIR} locale-gen >/dev/null
}

# auto_mdadm()
# add mdadm setup to existing /etc/mdadm.conf
auto_mdadm()
{
    if [ -e $DESTDIR/etc/mdadm.conf ];then
        if [ "$(cat /proc/mdstat | grep ^md)" ]; then
            DIALOG --infobox "Adding raid setup to $DESTDIR/etc/mdadm.conf ..." 4 40
            mdadm -Ds >> $DESTDIR/etc/mdadm.conf
        fi
    fi
}

# auto_network()
# configures network on host system according to installer
# settings if user wishes to do so
#
auto_network()
{
    # exit if network wasn't configured in installer
    if [ $S_NET -eq 0 ]; then
        return 1
    fi

    DIALOG --yesno "Do you want to use the previous network settings in rc.conf and resolv.conf?\nIf you used Proxy settings, they will be written to /etc/profile.d/proxy.sh" 0 0 || return 1

    if [ "$S_DHCP" != "1" ]; then
        sed -i -e "s#^eth.*#$INTERFACE=\"$INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST\"#g" ${DESTDIR}/etc/rc.conf
            if [ "$GW" != "" ]; then
                sed -i -e "s#gw 192.168.0.1#gw $GW#g" ${DESTDIR}/etc/rc.conf
                sed -i -e "s#!gateway#gateway#g" ${DESTDIR}/etc/rc.conf
            fi
        echo "nameserver $DNS" >> ${DESTDIR}/etc/resolv.conf
    else
        sed -i -e "s#^eth.*#$INTERFACE=\"dhcp\"#g" ${DESTDIR}/etc/rc.conf
    fi
        sed -i -e "s#eth0)#$INTERFACE)#g" ${DESTDIR}/etc/rc.conf
    if [ "$PROXY_HTTP" != "" ]; then
        echo "export http_proxy=$PROXY_HTTP" >> ${DESTDIR}/etc/profile.d/proxy.sh;
        chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
    fi
    if [ "$PROXY_FTP" != "" ]; then
        echo "export ftp_proxy=$PROXY_FTP" >> ${DESTDIR}/etc/profile.d/proxy.sh;
        chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
    fi
}

# donetwork()
# Hand-hold through setting up networking
#
# args: none
# returns: 1 on failure
donetwork() {
    INTERFACE=
    S_DHCP=
    ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
    if [ "$ifaces" = "" ]; then
        DIALOG --yesno "Cannot find any ethernet interfaces. You probably haven't loaded\nyour network module yet.  You have two options:\n\n  1) Probe for not detectable module now. (very old hardware)\n  2) Switch to another VC (ALT-F2) and load your module\n     with the modprobe command, then switch back here (ALT-F1)\n     and continue.\n\nIf you know which module you need, you should do Step 2 and\nselect NO below.  If you don't know which module you need,\nchoose Step 1 by selecting YES below.\n\nProbe for network module?" 18 70
        if [ $? -eq 0 ]; then
            net_notdetectable
        fi
        ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
        if [ "$ifaces" = "" ]; then
            DIALOG --msgbox "No network interfaces available." 0 0
            return 1
        fi
    fi
    while [ "$INTERFACE" = "" ]; do
        DIALOG --msgbox "Available Ethernet Interfaces:\n$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')\n\nIf your ethernet interface is not listed,\n1) Probe for the correct module now.\n2) Switch to another VC (ALT-F2) and load your module with\n   the modprobe command, then switch back here (ALT-F1)\n" 0 0
        ifaces=$(ifconfig -a | grep "Link encap:Ethernet"| sed 's/ \+Link encap:Ethernet \+HWaddr \+/ /g')
        DIALOG --extra-button --extra-label "Probe" --ok-label "Select" --menu "Select a network interface" 14 55 7 $ifaces 2>$ANSWER
        case $? in
            1) return 1 ;;
            0) INTERFACE=$(cat $ANSWER) ;;
            *) net_notdetectable ;;
        esac
    done
    # bring down everything, which could grab and affect the interface!
    [ -e /var/run/dhcpcd-$INTERFACE.pid ] && kill $(cat /var/run/dhcpcd-$INTERFACE.pid) && sleep 1
    [ "$(ifconfig | grep $INTERFACE)" ] && ifconfig $INTERFACE down >$LOG 2>&1
    [ "$(route | grep default)" ] && route del default >$LOG 2>&1
    [ -e /etc/resolv.conf ] && rm /etc/resolv.conf >$LOG 2>&1
    DIALOG --yesno "Do you want to use DHCP?" 0 0
    if [ $? -eq 0 ]; then
        DIALOG --infobox "Please wait.  Polling for DHCP server on $INTERFACE..." 10 65
        dhcpcd $INTERFACE >$LOG 2>&1
        if [ $? -ne 0 ]; then
            DIALOG --msgbox "Failed to run dhcpcd.  See $LOG for details." 0 0
            return 1
        fi
        if [ ! $(ifconfig $INTERFACE | grep 'inet addr:') ]; then
            DIALOG --msgbox "DHCP request failed." 0 0 || return 1
        fi
        S_DHCP=1
    else
        NETPARAMETERS=""
        while [ "$NETPARAMETERS" = "" ]; do
            DIALOG --inputbox "Enter your IP address" 8 65 "192.168.0.2" 2>$ANSWER || return 1
            IPADDR=$(cat $ANSWER)
            DIALOG --inputbox "Enter your netmask" 8 65 "255.255.255.0" 2>$ANSWER || return 1
            SUBNET=$(cat $ANSWER)
            DIALOG --inputbox "Enter your broadcast" 8 65 "192.168.0.255" 2>$ANSWER || return 1
            BROADCAST=$(cat $ANSWER)
            DIALOG --inputbox "Enter your gateway (optional)" 8 65 "192.168.0.1" 2>$ANSWER || return 1
            GW=$(cat $ANSWER)
            DIALOG --inputbox "Enter your DNS server IP" 8 65 "192.168.0.1" 2>$ANSWER || return 1
            DNS=$(cat $ANSWER)
            DIALOG --inputbox "Enter your HTTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 16 65 "" 2>$ANSWER || return 1
            PROXY_HTTP=$(cat $ANSWER)
            DIALOG --inputbox "Enter your FTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 16 65 "" 2>$ANSWER || return 1
            PROXY_FTP=$(cat $ANSWER)
            DIALOG --yesno "Are these settings correct?\n\nIP address:         $IPADDR\nNetmask:            $SUBNET\nGateway (optional): $GW\nDNS server:         $DNS\nHTTP proxy server:  $PROXY_HTTP\nFTP proxy server:   $PROXY_FTP" 0 0
            case $? in
                1) ;;
                0) NETPARAMETERS="1" ;;
            esac
        done
        echo "running: ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up" >$LOG
        ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up >$LOG 2>&1 || DIALOG --msgbox "Failed to setup $INTERFACE interface." 0 0 || return 1
        if [ "$GW" != "" ]; then
            route add default gw $GW >$LOG 2>&1 || DIALOG --msgbox "Failed to setup your gateway." 0 0 || return 1
        fi
        if [ "$PROXY_HTTP" = "" ]; then
            unset http_proxy
        else
            export http_proxy=$PROXY_HTTP
        fi
        if [ "$PROXY_FTP" = "" ]; then
            unset ftp_proxy
        else
            export ftp_proxy=$PROXY_FTP
        fi
        echo "nameserver $DNS" >/etc/resolv.conf
    fi
    ### Missing Proxy Configuration
    DIALOG --msgbox "The network is configured." 8 30
    NEXTITEM="1"
    S_NET=1
}

net_notdetectable() {
    # modules with no modalias exported! status kernel 2.6.18
    NOTDETECTABLE="hp ne de4x5 wd cs89x0 eepro smc9194 seeq8005 ni52 ni65 ac3200 smc-ultra at1700 hp-plus depca eexpress 82596 de600 eth16i de620 lance ewrk3 e2100 lp486e 3c501 3c503 3c505 3c507 3c509 3c515 myri10ge"
    for mod in ${NOTDETECTABLE}; do
        modprobe $mod >/dev/null 2>&1
    done
}

getrootfs() {
ROOTFS="$(blkid -c /dev/null $PART_ROOT -o value -s TYPE)"
}

getraidarrays() {
    RAIDARRAYS=""
    if ! [ "$(grep ^ARRAY $DESTDIR/etc/mdadm.conf)" ]; then
        RAIDARRAYS="$(echo -n $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's#\[[0-9]\]##g' -e 's# :.* raid[0-9]##g' -e 's#md#md=#g' -e 's# #,/dev/#g' -e 's#_##g'))"
    fi
}

getcryptsetup() {
    CRYPTSETUP=""
    if ! [ "$(cryptsetup status $(basename $PART_ROOT) | grep inactive)" ]; then
        #avoid clash with dmraid here
        if [ "$(cryptsetup status $(basename $PART_ROOT))" ]; then
            if [ "$UUIDPARAMETER" = "yes" ]; then
                CRYPTDEVICE="/dev/disk/by-uuid/$(echo $(blkid -s UUID -o value $(cryptsetup status $(basename $PART_ROOT) | grep device: | sed -e 's#device:##g')))"
                CRYPTNAME="$(basename $PART_ROOT)"
                CRYPTSETUP="cryptdevice=$CRYPTDEVICE:$CRYPTNAME"
            else
                CRYPTDEVICE="$(echo $(cryptsetup status $(basename $PART_ROOT) | grep device: | sed -e 's#device:##g'))"
                CRYPTNAME="$(basename $PART_ROOT)"
                CRYPTSETUP="cryptdevice=$CRYPTDEVICE:$CRYPTNAME"
            fi
        fi
    fi
}

dosyslinux() {
    getrootfs
    getraidarrays
    getcryptsetup
    if [ ! -e /usr/bin/syslinux ]; then
        DIALOG --msgbox "Error: Couldn't find syslinux binary. Is SYSLINUX installed?" 0 0
        return 1
    fi
    DIALOG --msgbox "Attention:\nIn order to get a booting system, you need the boot flag on the partition syslinux will boot the kernel from!" 0 0
    # look for a separately-mounted /boot partition
    bootdev=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
    if [ "$bootdev" = "" ]; then
        DIALOG --msgbox "Error: Couldn't find separate /boot partition." 0 0
        return 1
    fi
    # syslinux only can boot from vfat partitions!
    FSTYPE="$(blkid -c /dev/null $bootdev -o value -s TYPE)"
    if ! [ "$FSTYPE" = "vfat" ]; then
        DIALOG --msgbox "Error: Couldn't find vfat boot partition." 0 0
        return 1
    fi
    DEVS="$(findbootloaderdisks _)"
    DEVS="$DEVS $(findbootloaderpartitions _)"
    if [ "$DEVS" = "" ]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    DIALOG --menu "Select the boot device where the SYSLINUX bootloader will be installed (usually the MBR)" 14 55 7 $DEVS 2>$ANSWER || return 1
    ROOTDEV=$(cat $ANSWER)
    # generate syslinux.cfg
    TEMPDIR=/tmp
    MBR=/usr/lib/syslinux/mbr.bin
    [ -e ${TEMPDIR}/syslinux.cfg ] && rm ${TEMPDIR}/syslinux.cfg
    echo "prompt 1" >> ${TEMPDIR}/syslinux.cfg
    echo "timeout 300" >> ${TEMPDIR}/syslinux.cfg
    echo "display boot.msg" >> ${TEMPDIR}/syslinux.cfg
    echo "default arch"  >> ${TEMPDIR}/syslinux.cfg
    echo "label arch" >> ${TEMPDIR}/syslinux.cfg
    echo "kernel $VMLINUZ" >> ${TEMPDIR}/syslinux.cfg
    if [ "$UUIDPARAMETER" = "yes" ]; then
        local _rootpart="${PART_ROOT}"
        local _uuid="$(getuuid ${PART_ROOT})"
        if [ -n "${_uuid}" ]; then
            _rootpart="/dev/disk/by-uuid/${_uuid}"
        fi
        echo "append initrd=$KERNELPKG.img root=${_rootpart} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/syslinux.cfg
    else
        echo "append initrd=$KERNELPKG.img root=${PART_ROOT} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/syslinux.cfg
    fi
    echo "label fallback" >> ${TEMPDIR}/syslinux.cfg
    echo "kernel $VMLINUZ" >> ${TEMPDIR}/syslinux.cfg
    if [ "$UUIDPARAMETER" = "yes" ]; then
        echo "append initrd=$KERNELPKG-fallback.img root=${_rootpart} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/syslinux.cfg
    else
        echo "append initrd=$KERNELPKG-fallback.img root=${PART_ROOT} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP" | sed -e 's#  # #g' >> ${TEMPDIR}/syslinux.cfg
    fi
    # create boot message
    [ -e ${TEMPDIR}/boot.msg ] && rm ${TEMPDIR}/boot.msg
    echo "Arch Linux" >> ${TEMPDIR}/boot.msg
    echo "SYSLINUX BOOT" >> ${TEMPDIR}/boot.msg
    echo "" >> ${TEMPDIR}/boot.msg
    echo "Available labels:"  >> ${TEMPDIR}/boot.msg
    echo "- 'arch' for normal boot" >> ${TEMPDIR}/boot.msg
    echo "- 'fallback' for fallback boot" >> ${TEMPDIR}/boot.msg
    # edit syslinux.cfg
    DIALOG --msgbox "Before installing SYSLINUX, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, SYSLINUX will be installed." 0 0
    [ "$EDITOR" ] || geteditor
    $EDITOR ${TEMPDIR}/syslinux.cfg
    # install syslinux
    DIALOG --infobox "Installing the SYSLINUX bootloader..." 0 0
    cp  ${TEMPDIR}/syslinux.cfg ${DESTDIR}/boot/syslinux.cfg
    cp  ${TEMPDIR}/boot.msg ${DESTDIR}/boot/boot.msg
    cat ${MBR} > ${ROOTDEV}
    [ -e ${DESTDIR}/boot/ldlinux.sys ] && rm  ${DESTDIR}/boot/ldlinux.sys
    syslinux $bootdev >$LOG 2>&1
    if [ $? -gt 0 ]; then
        DIALOG --msgbox "Error installing SYSLINUX. (see $LOG for output)" 0 0
        return 1
    fi
    DIALOG --msgbox "SYSLINUX was successfully installed." 0 0
}

dolilo() {
    getrootfs
    getraidarrays
    getcryptsetup
    if [ ! -f $DESTDIR/etc/lilo.conf ]; then
        DIALOG --msgbox "Error: Couldn't find $DESTDIR/etc/lilo.conf. Is LILO installed?" 0 0
        return 1
    fi
    # Try to auto-configure LILO...
    if ! [ "$PART_ROOT" = "" -a "$S_LILO" = "1" ]; then
        if [ "$UUIDPARAMETER" = "yes" ]; then
            local _rootpart="${PART_ROOT}"
            local _uuid="$(getuuid ${PART_ROOT})"
            if [ -n "${_uuid}" ]; then
                _rootpart="/dev/disk/by-uuid/${_uuid}"
            fi
            sed -i "s|.*root=.*$|append=\"root=${_rootpart} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP\"|g" $DESTDIR/etc/lilo.conf
        else
            sed -i "s|.*root=.*$|append=\"root=${PART_ROOT} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP\"|g" $DESTDIR/etc/lilo.conf
        fi
        sed -i "s|image=/boot/vmlinuz26|image=/boot/$KERNELPKG|g" $DESTDIR/etc/lilo.conf
        sed -i "s|initrd=.*kernel26.*fallback.img$|initrd=/boot/$KERNELPKG-fallback.img|g" $DESTDIR/etc/lilo.conf
        sed -i "s|initrd=.*kernel26.img$|initrd=/boot/$KERNELPKG.img|g" $DESTDIR/etc/lilo.conf
        sed -i "s|initrd=.*kernel26-lts.img$|initrd=/boot/$KERNELPKG.img|g" $DESTDIR/etc/lilo.conf
    fi
    DEVS="$(findbootloaderdisks _)"
    DEVS="$DEVS $(findbootloaderpartitions _)"
    if [ "$DEVS" = "" ]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    DIALOG --menu "Select the boot device where the LILO bootloader will be installed (usually the MBR)" 14 55 7 $DEVS 2>$ANSWER || return 1
    ROOTDEV=$(cat $ANSWER)
    sed -i "s|boot=.*$|boot=$ROOTDEV|g" $DESTDIR/etc/lilo.conf
    DIALOG --msgbox "Before installing LILO, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, LILO will be installed." 0 0
    [ "$EDITOR" ] || geteditor
    $EDITOR ${DESTDIR}/etc/lilo.conf
    DIALOG --infobox "Installing the LILO bootloader..." 0 0
    chroot_mount
    chroot $DESTDIR /sbin/lilo >$LOG 2>&1
    if [ $? -gt 0 ]; then
        chroot_umount
        DIALOG --msgbox "Error installing LILO. (see $LOG for output)" 0 0
        return 1
    fi
    chroot_umount
    DIALOG --msgbox "LILO was successfully installed." 0 0
    S_LILO=1
}

dogrub() {
    _bootdev=""
    _grubdev=""
    bootdev=""
    grubdev=""
    redundant=""
    getrootfs
    getraidarrays
    getcryptsetup
    get_grub_map
    FAIL_RAID=""
    FAIL_DM=""
    if [ ! -f $DESTDIR/boot/grub/menu.lst ]; then
        DIALOG --msgbox "Error: Couldn't find $DESTDIR/boot/grub/menu.lst. Is GRUB installed?" 0 0
        return 1
    fi
    if ! [ "$(dmraid -r | grep ^no )" ]; then
        USE_DMRAID=""
        DIALOG --yesno "Setup detected dmraid device.\nDo you want to install grub on this device?" 0 0 && get_grub_dmraid_map
    fi
    # try to auto-configure GRUB...
    if [ "$PART_ROOT" != "" -a "$S_GRUB" != "1" ]; then
        # check if raid device, devicemapper or dmraid is used
        if [ "$(echo $PART_ROOT | grep /dev/md)" ]; then
            if [ "$(mdadm --detail $PART_ROOT | grep Level | sed -e 's#.*:\ ##g')" = "raid1" ]; then
                # get redundant devices
                for i in $(mdadm --detail $PART_ROOT | grep "\ /dev/" | sed -e 's#.* /#/#g'); do
                    _grubdev="$_grubdev $(mapdev $i)"
                done
                redundant="1"
            else
                # none raid1 devices are not bootable with grub, let it fail!
                FAIL_RAID="1"
            fi
            if [ "$(echo $PART_ROOT | grep /dev/md_d)" ]; then
                # partitionable raid is not supported by grub!
                FAIL_RAID="1"
            fi
        elif [ "$(echo $PART_ROOT | grep /dev/mapper)" ]; then
            # dmraid check
            if ! [ "$(dmsetup info $PART_ROOT | grep 'DMRAID')" ]; then
                FAIL_DM="1"
            else
                _grubdev=$(mapdev $PART_ROOT)
            fi
        else
            # use normal device
            _grubdev=$(mapdev $PART_ROOT)
        fi
        # look for a separately-mounted /boot partition
        bootdev=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
        # check if raid device, devicemapper or dmraid is used  on /boot partition
        if [ "$(echo $bootdev | grep /dev/md)" ]; then
            if [ "$(mdadm --detail $bootdev | grep Level | sed -e 's#.*:\ ##g')" = "raid1" ]; then
                # get redundant devices
                for i in $(mdadm --detail $bootdev | grep "\ /dev/" | sed -e 's#.* /#/#g'); do
                    _bootdev="$_bootdev $i"
                done
                redundant="1"
                # remove fail if /boot is raid1!
                FAIL_RAID=""
            else
                # none raid1 devices are not bootable with grub, let it fail!
                FAIL_RAID="1"
            fi
        elif  [ "$(echo $bootdev | grep /dev/mapper)" ]; then
                if ! [ "$(dmsetup info $bootdev | grep 'DMRAID')" ]; then
                    FAIL_DM="1"
                else
                    FAIL_DM=""
                    _bootdev=$bootdev
                fi
        else
            # remove fail if /boot is on other device!
            ! [ "$bootdev" = "" ] && FAIL_RAID=""
            ! [ "$bootdev" = "" ] && FAIL_DM=""
            if [ "$(echo $bootdev | grep /dev/md_d)" ]; then
                # partitionable raid is not supported by grub!
                FAIL_RAID="1"
            fi
            # use normal device
            _bootdev=$bootdev
        fi
        if [ "$FAIL_RAID" = "1" ]; then
                DIALOG --msgbox "Error: Grub cannot boot from none raid1 devices or partitionable raid devices!" 0 0
                return 1
        fi
        if [ "$FAIL_DM" = "1" ]; then
                DIALOG --msgbox "Error: Grub cannot boot from your created device mapper devices!" 0 0
                return 1
        fi
        if [ "$UUIDPARAMETER" = "yes" ]; then
            local _rootpart="${PART_ROOT}"
            local _uuid="$(getuuid ${PART_ROOT})"
            if [ -n "${_uuid}" ]; then
                _rootpart="/dev/disk/by-uuid/${_uuid}"
            fi
        fi
        if [ "$_grubdev" != "" -o "$_bootdev" != "" ]; then
            cp $DESTDIR/boot/grub/menu.lst /tmp/.menu.lst
            # remove the default entries by truncating the file at our little tag (#-*)
            head -n $(cat /tmp/.menu.lst | grep -n '#-\*' | cut -d: -f 1) /tmp/.menu.lst >$DESTDIR/boot/grub/menu.lst
            rm -f /tmp/.menu.lst
            subdir=
            # create correct entry array
            if [ "$_bootdev" != "" ]; then
                for bootdev in $_bootdev; do
                    _grubdev="$(mapdev $bootdev)"
                done
            else
                subdir="/boot"
            fi
            # keep the file from being completely bogus
            if [ "$_grubdev" = "DEVICE NOT FOUND" ]; then
                DIALOG --msgbox "Your root boot device could not be autodetected by setup.  Ensure you adjust the 'root (hd0,0)' line in your GRUB config accordingly." 0 0
                _grubdev="(hd0,0)"
            fi
            NUMBER=0
            # create default grub entries
            for grubdev in $_grubdev; do
                echo "" >>$DESTDIR/boot/grub/menu.lst
                echo "# ($NUMBER) Arch Linux" >>$DESTDIR/boot/grub/menu.lst
                echo "title  Arch Linux" >>$DESTDIR/boot/grub/menu.lst
                echo "root   $grubdev" >>$DESTDIR/boot/grub/menu.lst
                if [ "$UUIDPARAMETER" = "yes" ]; then
                    echo "kernel $subdir/$VMLINUZ root=${_rootpart} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/menu.lst
                else
                    echo "kernel $subdir/$VMLINUZ root=$PART_ROOT rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/menu.lst
                fi
                echo "initrd $subdir/$KERNELPKG.img" >>$DESTDIR/boot/grub/menu.lst
                echo "" >>$DESTDIR/boot/grub/menu.lst
                # adding fallback/full image
                NUMBER=$(($NUMBER+1))
                echo "# (($NUMBER) Arch Linux" >>$DESTDIR/boot/grub/menu.lst
                echo "title  Arch Linux Fallback" >>$DESTDIR/boot/grub/menu.lst
                echo "root   $grubdev" >>$DESTDIR/boot/grub/menu.lst
                if [ "$UUIDPARAMETER" = "yes" ]; then
                    echo "kernel $subdir/$VMLINUZ root=${_rootpart} rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/menu.lst
                else
                    echo "kernel $subdir/$VMLINUZ root=$PART_ROOT rootfstype=$ROOTFS $RAIDARRAYS $CRYPTSETUP ro" | sed -e 's#   # #g' | sed -e 's#  # #g' >>$DESTDIR/boot/grub/menu.lst
                fi
                echo "initrd $subdir/$KERNELPKG-fallback.img" >>$DESTDIR/boot/grub/menu.lst
                NUMBER=$(($NUMBER+1))
            done
            echo "" >>$DESTDIR/boot/grub/menu.lst
            echo "# ($NUMBER) Windows" >>$DESTDIR/boot/grub/menu.lst
            echo "#title Windows" >>$DESTDIR/boot/grub/menu.lst
            echo "#rootnoverify (hd0,0)" >>$DESTDIR/boot/grub/menu.lst
            echo "#makeactive" >>$DESTDIR/boot/grub/menu.lst
            echo "#chainloader +1" >>$DESTDIR/boot/grub/menu.lst
        fi
    fi

    DIALOG --msgbox "Before installing GRUB, you must review the configuration file.  You will now be put into the editor.  After you save your changes and exit the editor, you can install GRUB." 0 0
    [ "$EDITOR" ] || geteditor
    $EDITOR ${DESTDIR}/boot/grub/menu.lst

    DEVS="$(findbootloaderdisks _)"
    DEVS="$DEVS $(findbootloaderpartitions _)"
    if [ "$DEVS" = "" ]; then
        DIALOG --msgbox "No hard drives were found" 0 0
        return 1
    fi
    S_GRUB=""
    while [ "$S_GRUB" = "" ]; do
        DIALOG --menu "Select the boot device where the GRUB bootloader will be installed (usually the MBR  and not a partition)." 14 55 7 $DEVS 2>$ANSWER || return 1
        ROOTDEV=$(cat $ANSWER)
        DIALOG --infobox "Installing the GRUB bootloader..." 0 0
        cp -a $DESTDIR/usr/lib/grub/i386-pc/* $DESTDIR/boot/grub/
        sync
        # freeze xfs filesystems to enable grub installation on xfs filesystems
        if [ -x /usr/sbin/xfs_freeze ]; then
            if [ "$(cat /proc/mounts | grep "$DESTDIR/boot " | grep " xfs ")" ]; then
                /usr/sbin/xfs_freeze -f $DESTDIR/boot >/dev/null 2>&1
            fi
            if [ "$(cat /proc/mounts | grep "$DESTDIR " | grep " xfs ")" ]; then
                /usr/sbin/xfs_freeze -f $DESTDIR >/dev/null 2>&1
            fi
        fi
        # look for a separately-mounted /boot partition
        bootpart=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
        if [ "$(echo $bootpart | grep /dev/md)" ]; then
            bootpart=$(mdadm --detail $bootpart | grep $ROOTDEV | sed -e 's#.* /#/#g')
        fi
        if [ "$bootpart" = "" ]; then
            if [ "$PART_ROOT" = "" ]; then
                DIALOG --inputbox "Enter the full path to your root device" 8 65 "/dev/sda3" 2>$ANSWER || return 1
                bootpart=$(cat $ANSWER)
            else
                bootpart=$PART_ROOT
                if [ "$(echo $bootpart | grep /dev/md)" ]; then
                    bootpart=$(mdadm --detail $bootpart | grep $ROOTDEV | sed -e 's#.* /#/#g')
                fi
            fi
        fi
        bootpart=$(mapdev $bootpart)
        bootdev=$(mapdev $ROOTDEV)
        if [ "$bootpart" = "" ]; then
            DIALOG --msgbox "Error: Missing/Invalid root device: $bootpart" 0 0
            return 1
        fi
        if [ "$bootpart" = "DEVICE NOT FOUND" -o "$bootdev" = "DEVICE NOT FOUND" ]; then
            DIALOG --msgbox "GRUB root and setup devices could not be auto-located.  You will need to manually run the GRUB shell to install a bootloader." 0 0
            return 1
        fi
	get_chs
        ### HACK:we need a dmraid hack here! http://bugs.gentoo.org/show_bug.cgi?id=275566
        grub_dmraid_hack
        $DESTDIR/sbin/grub --device-map=/tmp/dev.map --no-floppy --batch >>/tmp/grub.log 2>&1 <<EOF
geometry $realdev $CYLINDERS $HEADS $SECTORS
root $bootpart
setup $bootdev
quit
EOF
        ### HACK:remove symlinks again! http://bugs.gentoo.org/show_bug.cgi?id=275566
        remove_grub_dmraid_hack
        cat /tmp/grub.log >$LOG
        # unfreeze xfs filesystems
        if [ -x /usr/sbin/xfs_freeze ]; then
            if [ "$(cat /proc/mounts | grep "$DESTDIR/boot " | grep " xfs ")" ]; then
                /usr/sbin/xfs_freeze -u $DESTDIR/boot >/dev/null 2>&1
            fi
            if [ "$(cat /proc/mounts | grep "$DESTDIR " | grep " xfs ")" ]; then
                /usr/sbin/xfs_freeze -u $DESTDIR >/dev/null 2>&1
            fi
        fi

        if grep "Error [0-9]*: " /tmp/grub.log >/dev/null; then
            DIALOG --msgbox "Error installing GRUB. (see $LOG for output)" 0 0
            return 1
        fi
        # copy device map file
        cp -f /tmp/dev.map $DESTDIR/boot/grub/device.map
        DIALOG --msgbox "GRUB was successfully installed." 0 0
        S_GRUB=1
        if [ "$(blkid -c /dev/null | grep TYPE=\"linux_raid_member\")" ]; then
            if [ "$redundant" = "1" ]; then
                DIALOG --defaultno --yesno "Setup detected a redundant software raid device.\nDo you want to install grub additionally to an other hard disk?" 0 0 && S_GRUB=""
            fi
        fi
    done
}

select_source()
{
    if ! [ $(which $DLPROG) ]; then
        DIALOG --menu "Please select an installation source" 10 35 3 \
        "1" "CD-ROM, USBSTICK or OTHER SOURCE" 2>$ANSWER || return 1
    else
        DIALOG --menu "Please select an installation source" 10 35 3 \
        "1" "CD-ROM, USBSTICK or OTHER SOURCE" \
        "2" "FTP/HTTP" 2>$ANSWER || return 1
    fi

    case $(cat $ANSWER) in
        "1")
            MODE="media"
            ;;
        "2")
            MODE="ftp"
            ;;
    esac

    if [ "$MODE" = "media" ]; then
        TITLE="Arch Linux CDROM, USBSTICK or OTHER SOURCE Installation"
        getsource
    else
        DEFAULT=
        TITLE="Arch Linux FTP/HTTP Installation"
        while true; do
            if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
            else
            DEFAULT=""
            fi
            CANCEL=""
            DIALOG $DEFAULT --menu "FTP Installation" 10 35 3 \
            "0" "Setup Network" \
            "1" "Choose Mirror" \
            "2" "Return to Main Menu" 2>$ANSWER || CANCEL="1"

            case "$(cat $ANSWER)" in
            "0")
                donetwork ;;
            "1")
                getsource ;;
             *)
                break ;;
            esac
        done
    fi
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

set_clock()
{
    if [ -e /usr/bin/tz ]; then
        tz --setup && NEXTITEM="2"
    else
        DIALOG --msgbox "Error:\ntz script not found, aborting clock setting" 0 0
    fi
}

set_keyboard()
{
    if [ -e /usr/bin/km ]; then
        km --setup && NEXTITEM="1"
    else
        DIALOG --msgbox "Error:\nkm script not found, aborting keyboard and console setting" 0 0
    fi
}

# run_mkinitcpio()
# runs mkinitcpio on the target system, displays output
#
run_mkinitcpio()
{
    chroot_mount
    # all mkinitcpio output goes to /tmp/mkinitcpio.log, which we tail into a dialog
    ( \
    touch /tmp/setup-mkinitcpio-running
    echo "Initramfs progress ..." > /tmp/initramfs.log; echo >> /tmp/mkinitcpio.log
    chroot $DESTDIR /sbin/mkinitcpio -p $KERNELPKG >>/tmp/mkinitcpio.log 2>&1
    echo >> /tmp/mkinitcpio.log
    rm -f /tmp/setup-mkinitcpio-running
    ) &
    sleep 2
    dialog --backtitle "$TITLE" --title "Rebuilding initramfs images ..." --no-kill --tailboxbg "/tmp/mkinitcpio.log" 18 70
    while [ -f /tmp/setup-mkinitcpio-running ]; do
        sleep 1
    done
    chroot_umount
}

prepare_harddrive()
{
    S_MKFSAUTO=0
    S_MKFS=0
    DONE=0
    UUIDPARAMETER=""
    NEXTITEM=""
    DIALOG --yesno "Do you want to use UUID device name scheme,\ninstead of kernel device name scheme?" 0 0 && UUIDPARAMETER=yes
    while [ "$DONE" = "0" ]; do
        if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog $DEFAULT --backtitle "$TITLE" --menu "Prepare Hard Drive" 12 60 5 \
            "1" "Auto-Prepare (erases the ENTIRE hard drive)" \
            "2" "Partition Hard Drives" \
            "3" "Create Software Raid, Lvm2 and Luks encryption" \
            "4" "Set Filesystem Mountpoints" \
            "5" "Return to Main Menu" 2>$ANSWER || CANCEL="1"
        NEXTITEM="$(cat $ANSWER)"
        [ "$S_MKFSAUTO" = "1" ] && DONE=1
        case $(cat $ANSWER) in
            "1")
                autoprepare
                [ "$S_MKFSAUTO" = "1" ] && DONE=1
                ;;
            "2")
                partition ;;
            "3")
                create_special ;;
            "4")
                PARTFINISH=""
                mountpoints ;;
            *)
                DONE=1 ;;
        esac
    done
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="2"
    else
        NEXTITEM="3"
    fi
}

# menu for raid, lvm and encrypt
create_special()
{
    NEXTITEM=""
    SPECIALDONE=0
    while [ "$SPECIALDONE" = "0" ]; do
        if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog $DEFAULT --backtitle "$TITLE" --menu "Create Software Raid, LVM2 and Luks encryption" 14 60 5 \
            "1" "Create Software Raid" \
            "2" "Create LVM2" \
            "3" "Create Luks encryption" \
            "4" "Return to Previous Menu" 2>$ANSWER || CANCEL="1"
        NEXTITEM="$(cat $ANSWER)"
        case $(cat $ANSWER) in
            "1")
                _createmd ;;
            "2")
                _createlvm ;;
            "3")
                _createluks ;;
            *)
                SPECIALDONE=1 ;;
        esac
    done
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

# menu for md creation
_createmd()
{
    NEXTITEM=""
    MDDONE=0
    while [ "$MDDONE" = "0" ]; do
        if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog $DEFAULT --backtitle "$TITLE" --menu "Create Software Raid" 12 60 5 \
            "1" "Raid Help" \
            "2" "Reset Software Raid completely" \
            "3" "Create Software Raid" \
            "4" "Create Partitionable Software Raid" \
            "5" "Return to Previous Menu" 2>$ANSWER || CANCEL="1"
        NEXTITEM="$(cat $ANSWER)"
        case $(cat $ANSWER) in
            "1")
                _helpraid ;;
            "2")
                _stopmd ;;
            "3")
                _raid ;;
            "4")
                _raidpartitions ;;
              *)
                MDDONE=1 ;;
        esac
    done
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="1"
    else
        NEXTITEM="4"
    fi
}

# menu for lvm creation
_createlvm()
{
    NEXTITEM=""
    LVMDONE=0
    while [ "$LVMDONE" = "0" ]; do
        if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog $DEFAULT --backtitle "$TITLE" --menu "Create physical volume, volume group or logical volume" 13 60 7 \
            "1" "LVM Help" \
            "2" "Reset Logical Volume completely" \
            "3" "Create Physical Volume" \
            "4" "Create Volume Group" \
            "5" "Create Logical Volume" \
            "6" "Return to Previous Menu" 2>$ANSWER || CANCEL="1"
        NEXTITEM="$(cat $ANSWER)"
        case $(cat $ANSWER) in
            "1")
                _helplvm ;;
            "2")
                _stoplvm ;;
            "3")
                _createpv ;;
            "4")
                _createvg ;;
            "5")
                _createlv ;;
              *)
                LVMDONE=1 ;;
        esac
    done
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="2"
    else
        NEXTITEM="4"
    fi
}

# menu for luks creation
_createluks()
{
    NEXTITEM=""
    LUKSDONE=0
    while [ "$LUKSDONE" = "0" ]; do
        if [ -n "$NEXTITEM" ]; then
            DEFAULT="--default-item $NEXTITEM"
        else
            DEFAULT=""
        fi
        CANCEL=""
        dialog $DEFAULT --backtitle "$TITLE" --menu "Create Luks Encryption" 12 60 5 \
            "1" "Luks Help" \
            "2" "Reset Luks Encryption completely" \
            "3" "Create Luks" \
            "4" "Return to Previous Menu" 2>$ANSWER || CANCEL="1"
        NEXTITEM="$(cat $ANSWER)"
        case $(cat $ANSWER) in
            "1")
                _helpluks ;;
            "2")
                _stopluks ;;
            "3")
                _luks ;;
              *)
                LUKSDONE=1 ;;
        esac
    done
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="3"
    else
        NEXTITEM="4"
    fi
}

do_pacmanmirror()
{
    SAMEMIRROR=""
    mirrorlist="${DESTDIR}/etc/pacman.d/mirrorlist"
    if [ "$MODE" = "ftp" -a "${SYNC_URL}" != "" ]; then
        DIALOG --yesno "Would you like to use the same MIRROR you used for installation?" 0 0 && SAMEMIRROR="yes"
    fi
    if ! [ "$SAMEMIRROR" = "yes" ]; then
        DIALOG --msgbox "WARNING:\n\n- Please keep in mind ftp.archlinux.org is throttled!\n- Please select another mirror to get full download speed." 18 70
        # this will find all mirrors in the mirrorlist, commented out or not
        PAC_MIRRORS=$(egrep -o '((ftp)|(http))://[^/]*' "$mirrorlist" | sed 's|$| _|g')
        DIALOG --menu "Select the primary Pacman mirror" 14 55 7 $PAC_MIRRORS "Custom" "_" 2>$ANSWER || return 1
        PAC_SYNC_SERVER="$(cat $ANSWER)"
        if [ "$PAC_SYNC_SERVER" = "Custom" ]; then
            DIALOG --inputbox "Enter the full URL to packages, for example:\nhttp://server.org/archlinux/\$repo/os/$(uname -m)" 8 65 "http://" 2>$ANSWER || return 1
            PAC_SYNC_SERVER="$(cat $ANSWER)"
        else
            # Form the full URL for our mirror by grepping for the
            # server name in our mirrorlist and pulling the full URL
            # out. Ensure that if it was listed twice we only return
            # one line for the mirror.
            PAC_SYNC_SERVER=$(egrep -o "${PAC_SYNC_SERVER}.*" "$mirrorlist" | head -n1)
        fi
    else
        PAC_SYNC_SERVER="${SYNC_URL}"
    fi
    # comment out all existing mirrors
    sed -i -e 's/^Server/#Server/g' "$mirrorlist"
    # add our new entry at the end of the file
    echo "# Setup-configured entry" >> "$mirrorlist"
    echo "Server = $PAC_SYNC_SERVER" >> "$mirrorlist"
}

auto_hwdetect()
{
    HWDETECT=""
    FBPARAMETER=""
    HWPARAMETER=""
    HWDETECTMODULES=""
    HWDETECTHOOKS=""
    HWDETECTFILES=""
    HWDETECTRC=""
    DIALOG --yesno "PRECONFIGURATION?\n-----------------\n\nDo you want to use 'hwdetect' for:\n'/etc/rc.conf' and '/etc/mkinitcpio.conf'?\n\nThis ensures consistent ordering of your hard disk / usb controllers, network and sound devices.\n\nIt is recommended to say 'YES' here." 18 70 && HWDETECT="yes"
    if [ "$HWDETECT" = "yes" ]; then
        # check if running in vmware
        [ "$(vmware-detect)" ] && HWPARAMETER="$HWPARAMETER --vmware"
        # check on ide-legacy boot parameter
        [ "$(grep -w ide-legacy /proc/cmdline)" ] && HWPARAMETER="$HWPARAMETER --ide-legacy"
        # check on used keymap
        ! [ "$(grep '^KEYMAP="us"' $DESTDIR/etc/rc.conf)" ] && HWPARAMETER="$HWPARAMETER --keymap"
        # check on usb input
        [ "$(grep hid /proc/modules)" ] && HWPARAMETER="$HWPARAMETER --usbinput"
        # check on framebuffer modules and kms
        if [ -e $DESTDIR/lib/initcpio/hooks/v86d -a "$(grep -w uvesafb /proc/cmdline)" ]; then
             FBPARAMETER="--uvesafb"
             HWDETECTFILES="/etc/modprobe.d/uvesafb.conf"
        fi
        [ "$(grep -w ati-kms /proc/cmdline)" ] && (FBPARAMETER="--ati-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [ "$(grep -w intel-kms /proc/cmdline)" ] && (FBPARAMETER="--intel-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [ "$(grep -w nvidia-kms /proc/cmdline)" ] && (FBPARAMETER="--nvidia-kms";HWDETECTFILES="/etc/modprobe.d/modprobe.conf")
        [ "$(grep -w fbmodule /proc/cmdline)" ] && FBPARAMETER="--fbmodule"
        if [ "$(grep usb_storage /proc/modules)" ]; then
            DIALOG --defaultno --yesno "Setup detected usb storage driver...\nDo you need support for booting from usb devices?" 0 0 && HWPARAMETER="$HWPARAMETER --usb"
        fi
        if [ "$(grep sbp2 /proc/modules)" ]; then
            DIALOG --defaultno --yesno "Setup detected firewire storage driver...\nDo you need support for booting from firewire devices?" 0 0 && HWPARAMETER="$HWPARAMETER --fw"
        fi
        if [ "$(grep pcmcia /proc/modules)" ]; then
            DIALOG --defaultno --yesno "Setup detected pcmcia hardware...\nDo you need support for booting from pcmcia devices?" 0 0 && HWPARAMETER="$HWPARAMETER --pcmcia"
        fi
        if [ "$(grep nfs /proc/modules)" ]; then
            DIALOG --defaultno --yesno "Setup detected nfs driver...\nDo you need support for booting from nfs shares?" 0 0 && HWPARAMETER="$HWPARAMETER --nfs"
        fi
        if [ -e $DESTDIR/lib/initcpio/hooks/dmraid ]; then
            if ! [ "$(dmraid -r | grep ^no )" ]; then
                HWPARAMETER="$HWPARAMETER --dmraid"
            fi
        fi
        HWDETECTMODULES="$(echo $(hwdetect $FBPARAMETER --hostcontroller --filesystem $HWPARAMETER) | sed -e 's#.*\" ##g')"
        HWDETECTHOOKS="$(hwdetect --rootdevice=$PART_ROOT --hooks-dir=$DESTDIR/lib/initcpio/install --hooks $FBPARAMETER $HWPARAMETER)"
        HWDETECTRC="$(echo $(hwdetect --net --sound $HWPARAMETER)| sed -e 's#.*) ##g')"
        [ -n "$HWDETECTMODULES" ] && sed -i -e "s/^MODULES=.*/$HWDETECTMODULES/g" ${DESTDIR}/etc/mkinitcpio.conf
        [ -n "$HWDETECTHOOKS" ] && sed -i -e "s/^HOOKS=.*/$HWDETECTHOOKS/g" ${DESTDIR}/etc/mkinitcpio.conf
        [ -n "$HWDETECTFILES" ] && sed -i -e "s#^FILES=.*#FILES=\"$HWDETECTFILES\"#g" ${DESTDIR}/etc/mkinitcpio.conf
        [ -n "$HWDETECTRC" ] && sed -i -e "s/^MODULES=.*/$HWDETECTRC/g" ${DESTDIR}/etc/rc.conf
    fi
}

auto_fb()
{
    UVESAFB=""
    if [ "$(grep -w ati-kms /proc/cmdline)" -o "$(grep -w intel-kms /proc/cmdline)" -o "$(grep -w nvidia-kms /proc/cmdline)" ]; then
        # clean modprobe.conf file from options first
        sed -i -e '/options/d' $DESTDIR/etc/modprobe.d/modprobe.conf
        ! [ "$(grep nouveau $DESTDIR/etc/modprobe.d/modprobe.conf)" ] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> $DESTDIR/etc/modprobe.d/modprobe.conf
        ! [ "$(grep i915 $DESTDIR/etc/modprobe.d/modprobe.conf)" ] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> $DESTDIR/etc/modprobe.d/modprobe.conf
        ! [ "$(grep radeon $DESTDIR/etc/modprobe.d/modprobe.conf)" ] && grep ^[a-z] /etc/modprobe.d/modprobe.conf >> $DESTDIR/etc/modprobe.d/modprobe.conf
    fi
    if [ -e $DESTDIR/lib/initcpio/hooks/v86d -a "$(grep -w uvesafb /proc/cmdline)" ]; then
        UVESAFB="$(grep ^[a-z] /etc/modprobe.d/uvesafb.conf)" 
        sed -i -e "s#options.*#$UVESAFB#g" $DESTDIR/etc/modprobe.d/uvesafb.conf
    fi
}

auto_parameters()
{
    if [ -s /tmp/.keymap ]; then
        DIALOG --infobox "Setting the keymap: $(cat /tmp/.keymap | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^KEYMAP=.*/KEYMAP=\"$(cat /tmp/.keymap | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [ -s /tmp/.font ]; then
        DIALOG --infobox "Setting the consolefont: $(cat /tmp/.font | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^CONSOLEFONT=.*/CONSOLEFONT=\"$(cat /tmp/.font | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [ -s  /tmp/.hardwareclock ]; then
        DIALOG --infobox "Setting the hardwareclock: $(cat /tmp/.hardwareclock | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s/^HARDWARECLOCK=.*/HARDWARECLOCK=\"$(cat /tmp/.hardwareclock | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
    fi
    if [ -s  /tmp/.timezone ]; then
        DIALOG --infobox "Setting the timezone: $(cat /tmp/.timezone | sed -e 's/\..*//g') in rc.conf ..." 0 0
        sed -i -e "s#^TIMEZONE=.*#TIMEZONE=\"$(cat /tmp/.timezone | sed -e 's/\..*//g')\"#g" ${DESTDIR}/etc/rc.conf
    fi
}

auto_luks()
{
    if [ -e /tmp/.crypttab -a "$(grep -v '^#' ${DESTDIR}/etc/crypttab)"  = "" ]; then
        sed -i -e "/$(basename ${PART_ROOT})/d" /tmp/.crypttab
        cat /tmp/.crypttab >> ${DESTDIR}/etc/crypttab
    fi
}

auto_timesetting()
{
    TIMEZONE=""
    eval $(grep "^TIMEZONE" ${DESTDIR}/etc/rc.conf)
    if [ "$TIMEZONE" != "" -a -e ${DESTDIR}/usr/share/zoneinfo/$TIMEZONE ]; then
        cp ${DESTDIR}/usr/share/zoneinfo/$TIMEZONE ${DESTDIR}/etc/localtime
        cp ${DESTDIR}/usr/share/zoneinfo/$TIMEZONE /etc/localtime
    fi
    if [ ! -f ${DESTDIR}/var/lib/hwclock/adjtime ]; then
        echo "0.0 0 0.0" > ${DESTDIR}/var/lib/hwclock/adjtime
    fi
}

auto_ftpmirror()
{
    # /etc/pacman.d/mirrorlist
    # add installer-selected mirror to the top of the mirrorlist
    if [ "$MODE" = "ftp" -a "${SYNC_URL}" != "" ]; then
        SYNC_URL="${SYNC_URL}"
        awk "BEGIN { printf(\"# Mirror used during installation\nServer = "${SYNC_URL}"\n\n\") } 1 " "${DESTDIR}/etc/pacman.d/mirrorlist" > /tmp/inst-mirrorlist
        mv /tmp/inst-mirrorlist "${DESTDIR}/etc/pacman.d/mirrorlist"
    fi
}

configure_system()
{

    ## PREPROCESSING ##
    # only done on first invocation of configure_system and redone on canceled configure system
    if [ $S_CONFIG -eq 0 ]; then
        auto_ftpmirror
        auto_network
        auto_parameters
        auto_fb
        auto_hwdetect
    fi
    ## END PREPROCESS ##
    [ "$EDITOR" ] || geteditor
    FILE=""

    # main menu loop
    while true; do
        S_CONFIG=0
        if [ -n "$FILE" ]; then
            DEFAULT="--default-item $FILE"
        else
            DEFAULT=""
        fi
        DIALOG $DEFAULT --menu "Configuration" 20 80 16 \
            "/etc/rc.conf"                  "System Config" \
            "/etc/fstab"                    "Filesystem Mountpoints" \
            "/etc/mkinitcpio.conf"          "Initramfs Config" \
            "/etc/modprobe.d/modprobe.conf" "Kernel Modules" \
            "/etc/resolv.conf"              "DNS Servers" \
            "/etc/hosts"                    "Network Hosts" \
            "/etc/hosts.deny"               "Denied Network Services" \
            "/etc/hosts.allow"              "Allowed Network Services" \
            "/etc/locale.gen"               "Glibc Locales" \
            "Pacman-Mirror"                 "Set the primary pacman mirror" \
            "/etc/pacman.d/mirrorlist"      "Pacman Mirror List" \
            "/etc/pacman.conf"              "Pacman Config File" \
            "Root-Password"                 "Set the root password" \
            "Return"                        "Return to Main Menu" 2>$ANSWER || break
        FILE="$(cat $ANSWER)"

        if [ "$FILE" = "Return" -o -z "$FILE" ]; then       # exit
            S_CONFIG=1
            break
        elif [ "$FILE" = "/etc/mkinitcpio.conf" ]; then    # non-file
            DIALOG --msgbox "The mkinitcpio.conf file controls which modules will be placed into the initramfs for your system's kernel.\n\n- Non US keymap users should add 'keymap' to HOOKS= array\n- USB keyboard users should add 'usbinput' to HOOKS= array\n- If you install under VMWARE add 'BusLogic' to MODULES= array\n- raid, lvm2, encrypt are not enabled by default\n- 2 or more disk controllers, please specify the correct module\n  loading order in MODULES= array \n\nMost of you will not need to change anything in this file." 18 70
            HOOK_ERROR=""
            $EDITOR ${DESTDIR}${FILE}
            for i in $(cat ${DESTDIR}/etc/mkinitcpio.conf | grep ^HOOKS | sed -e 's/"//g' -e 's/HOOKS=//g'); do
                [ -e ${DESTDIR}/lib/initcpio/install/$i ] || HOOK_ERROR=1
            done
            if [ "$HOOK_ERROR" = "1" ]; then
                DIALOG --msgbox "ERROR: Detected error in 'HOOKS=' line, please correct HOOKS= in /etc/mkinitcpio.conf!" 18 70
            fi
        elif [ "$FILE" = "/etc/locale.gen" ]; then          # non-file
            # enable glibc locales from rc.conf
                for i in $(grep "^LOCALE" ${DESTDIR}/etc/rc.conf | sed -e 's/.*="//g' -e's/\..*//g'); do
                    sed -i -e "s/^#$i/$i/g" ${DESTDIR}/etc/locale.gen
                done
            $EDITOR ${DESTDIR}${FILE}
        elif [ "$FILE" = "Root-Password" ]; then            # non-file
            PASSWORD=""
            while [ "${PASSWORD}" = "" ]; do
                DIALOG --insecure --passwordbox "Enter root password:" 0 0 2>$ANSWER || return 1
                PASS=$(cat $ANSWER)
                DIALOG --insecure --passwordbox "Retype root password:" 0 0 2>$ANSWER || return 1
                PASS2=$(cat $ANSWER)
                if [ "$PASS" = "$PASS2" ]; then
                    PASSWORD=$PASS
                    echo $PASSWORD > /tmp/.password
                    echo $PASSWORD >> /tmp/.password
                    PASSWORD=/tmp/.password
                else
                    DIALOG --msgbox "Password didn't match, please enter again." 0 0
                fi
            done
            chroot ${DESTDIR} passwd root < /tmp/.password
            rm /tmp/.password
        elif [ "$FILE" = "Pacman-Mirror" ]; then            # non-file
            do_pacmanmirror
        else                                                #regular file
            $EDITOR ${DESTDIR}${FILE}
        fi
    done
    if [ $S_CONFIG -eq 1 ]; then
        # only done on normal exit of configure menu
        ## POSTPROCESSING ##
        # adjust time
        auto_timesetting
        # /etc/initcpio.conf
        run_mkinitcpio
        # /etc/locale.gen
        chroot ${DESTDIR} locale-gen >/dev/null 2>&1
        ## END POSTPROCESSING ##
        NEXTITEM="7"
    fi
}

install_bootloader()
{
    CANCEL=""
    DIALOG --menu "Which bootloader would you like to use?  Grub is the Arch default.\n\n" \
        12 55 3 \
        "GRUB" "Use the GRUB bootloader (default)" \
        "LILO" "Use the LILO bootloader" \
        "SYSLINUX" "Use the SYSLINUX bootloader" 2>$ANSWER || CANCEL=1
    case $(cat $ANSWER) in
        "GRUB") dogrub ;;
        "LILO") dolilo ;;
        "SYSLINUX") dosyslinux ;;
    esac
    if [ "$CANCEL" = "1" ]; then
        NEXTITEM="7"
    else
        NEXTITEM="8"
    fi
}

mainmenu() {
    if [ -n "$NEXTITEM" ]; then
        DEFAULT="--default-item $NEXTITEM"
    else
        DEFAULT=""
    fi
    dialog $DEFAULT --backtitle "$TITLE" --title " MAIN MENU " \
    --menu "Use the UP and DOWN arrows to navigate menus.  Use TAB to switch between buttons and ENTER to select." 17 55 13 \
    "0" "Set Keyboard And Console Font" \
    "1" "Set Time and Date" \
    "2" "Prepare Hard Drive" \
    "3" "Select Source" \
    "4" "Select Packages" \
    "5" "Install Packages" \
    "6" "Configure System" \
    "7" "Install Bootloader" \
    "8" "Exit Install" 2>$ANSWER
    NEXTITEM="$(cat $ANSWER)"
    case $(cat $ANSWER) in
        "0")
            set_keyboard ;;
        "1")
            set_clock ;;
        "2")
            prepare_harddrive ;;
        "3")
            select_source ;;
        "4")
            select_packages ;;
        "5")
            installpkg ;;
        "6")
            configure_system ;;
        "7")
            install_bootloader ;;
        "8")
            if [ "$S_SRC" = "1" -a "$MODE" = "media" ]; then
                umount /src >/dev/null 2>&1
            fi
            [ -e /tmp/.setup-running ] && rm /tmp/.setup-running
            clear
            echo ""
            echo "If the install finished successfully, you can now type 'reboot'"
            echo "to restart the system."
            echo ""
            exit 0 ;;
        *)
            DIALOG --yesno "Abort Installation?" 6 40 && [ -e /tmp/.setup-running ] && rm /tmp/.setup-running && clear && exit 0
            ;;
    esac
}

#####################
## begin execution ##
if [ -e /tmp/.setup-running ]; then
    echo "HINT:"
    echo "setup already runs on a different console!"
    echo "Please remove /tmp/.setup-running first to launch setup!"
    exit 1
fi
: >/tmp/.setup-running
: >/tmp/.setup

DIALOG --msgbox "Welcome to the Arch Linux Installation program.  The install process is fairly straightforward, and you should run through the options in the order they are presented.  If you are unfamiliar with partitioning/making filesystems, you may want to consult some documentation before continuing.  You can view all output from commands by viewing your VC7 console (ALT-F7).  ALT-F1 will bring you back here." 14 65

while true; do
    mainmenu
done

clear
exit 0

# vim: set ts=4 sw=4 et:
