#!/bin/bash

ANSWER="/tmp/.setup"
TITLE="Arch Linux Installation"
LOG="/dev/tty5"
DESTDIR="/mnt"
EDITOR=

# name of the kernel image
VMLINUZ="vmlinuz26"

# abstract the common pacman args
PACMAN="pacman --root ${DESTDIR} --config /tmp/pacman.conf --noconfirm"

# sources
SRC_READY=0
SYNC_URL=
MIRRORLIST="/etc/pacman.d/mirrorlist"

# partitions
PART_ROOT=
PART_SWAP=

PATH=$PATH:/tmp/bin:/tmp/usr/bin:/tmp/sbin:/tmp/usr/sbin

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

# install stages
S_NET=0
S_PART=0
S_MKFS=0
S_MKFSAUTO=0
S_SELECT=0
S_INSTALL=0
S_LILO=0
S_GRUB=0
S_KERNEL=0

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

abort()
{
    dodialog yesno "Abort Installation?" 6 40 || return 0
    exit 0
}

msg()
{
    dodialog msgbox "$1"
    return 1
}

dodialog()
{
    # use this for msgbox, inputbox, yesno, infobox
    #
    # dodialog <boxtype> <text> [height] [width] [other]
    # 26/3/06: added an option so that if [other] is default=no
    #      the dialog will default to no
    # the new dialog's auto-sizing is pretty dumb, we can't trust it
    height=12
    width=65
    if [ "$3" != "" ]; then
        height=$3
    fi
    if [ "$4" != "" ]; then
        width=$4
    fi
    if [ "$5" = "default=no"  ]; then
        dialog --defaultno --backtitle "$TITLE" --aspect 15 --$1 "$2" $height $width

    else
        dialog --backtitle "$TITLE" --aspect 15 --$1 "$2" $height $width $5
    fi
}

domenu()
{
    menutype=$1 ; shift
    text=$1     ; shift
    height=$1   ; shift
    width=$1    ; shift
    mheight=$1  ; shift

    dialog --backtitle "$TITLE" --$menutype "$text" $height $width $mheight $*
}

finddisks() {
    workdir="$PWD"
    cd /sys/block
    # ide devices
    for dev in $(ls | egrep '^hd'); do
        if [ "$(cat $dev/device/media)" = "disk" ]; then
            if [ "$(dmesg | grep sectors | grep $dev)" ]; then
                echo "/dev/$dev"
                [ "$1" ] && echo $1
            fi
        fi
    done
    #scsi/sata devices
    for dev in $(ls | egrep '^sd'); do
        if ! [ "$(cat $dev/device/type)" = "5" ]; then
            if [ "$(dmesg | grep sectors | grep $dev)" ]; then
                echo "/dev/$dev"
                [ "$1" ] && echo $1
            fi
        fi
    done
    # cciss controllers
    if [ -d /dev/cciss ] ; then
        cd /dev/cciss
        for dev in $(ls | egrep -v 'p'); do
            echo "/dev/cciss/$dev"
            [ "$1" ] && echo $1
        done
    fi
    # Smart 2 controllers
        if [ -d /dev/ida ] ; then
                cd /dev/ida
                for dev in $(ls | egrep -v 'p'); do
                        echo "/dev/ida/$dev"
                        [ "$1" ] && echo $1
                done
        fi
    cd "$workdir"
}

# 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}" ]; then
        echo "$(blkid -s UUID -o value ${1})"
    fi
}

findpartitions() {
    workdir="$PWD"
    for devpath in $(finddisks); do
        disk=$(echo $devpath | sed 's|.*/||')
        cd /sys/block/$disk
        for part in $disk*; do
            # check if not already assembled to a raid device
            if ! [ "$(cat /proc/mdstat 2>/dev/null | grep $part)" -o "$(fstype 2>/dev/null </dev/$part | grep "lvm2")" -o "$(sfdisk -c /dev/$disk $(echo $part | sed -e "s#$disk##g") 2>/dev/null | grep "5")" ]; then
                if [ -d $part ]; then
                    echo "/dev/$part"
                    [ "$1" ] && echo $1
                fi
            fi
        done
    done
    # include any mapped devices
    for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control); do
        echo "/dev/mapper/$devpath"
        [ "$1" ] && echo $1
    done
    # include any raid md devices
    for devpath in $(ls -d /dev/md* | grep '[0-9]' 2>/dev/null); do
        if cat /proc/mdstat | grep -qw $(echo $devpath | sed -e 's|/dev/||g'); then
        echo "$devpath"
        [ "$1" ] && echo $1
        fi
    done
    # inlcude cciss controllers
    if [ -d /dev/cciss ] ; then
        cd /dev/cciss
        for dev in $(ls | egrep 'p'); do
            echo "/dev/cciss/$dev"
            [ "$1" ] && echo $1
        done
    fi
    # inlcude Smart 2 controllers
    if [ -d /dev/ida ] ; then
        cd /dev/ida
        for dev in $(ls | egrep 'p'); do
            echo "/dev/ida/$dev"
            [ "$1" ] && echo $1
        done
    fi
    cd "$workdir"
}

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

mapdev() {
    partition_flag=0
    device_found=0
    devs=$(cat /tmp/dev.map | grep -v fd | sed 's/ *\t/ /' | sed ':a;$!N;$!ba;s/\n/ /g')
    linuxdevice=$(echo $1 | cut -b1-8)
    if [ "$(echo $1 | egrep '[0-9]$')" ]; then
        # /dev/hdXY
        pnum=$(echo $1 | cut -b9-)
        pnum=$(($pnum-1))
        partition_flag=1
    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
}

convertdev() {
    # assume a /dev/hdX or /dev/hdXY name
    letter=$(echo $1 | cut -b8)
    case $letter in
        "a") dnum=0 ;;
        "b") dnum=1 ;;
        "c") dnum=2 ;;
        "d") dnum=3 ;;
        "e") dnum=4 ;;
        "f") dnum=5 ;;
        "g") dnum=6 ;;
        "h") dnum=7 ;;
        *) return
    esac

    if [ "$(echo $1 | egrep '[0-9]$')" ]; then
        # /dev/hdXY
        pnum=$(echo $1 | cut -b9-)
        pnum=$(($pnum-1))
        echo "(hd${dnum},${pnum})"
    else
        # /dev/hdX
        echo "(hd${dnum})"
    fi
}

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

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

geteditor() {
    dialog --backtitle "$TITLE" --menu "Select a Text Editor to Use" 10 35 3 \
        "1" "nano (easier)" \
        "2" "vi" 2>$ANSWER
    case $(cat $ANSWER) in
        "1") EDITOR="nano" ;;
        "2") EDITOR="vi" ;;
        *)   EDITOR="nano" ;;
    esac
}

_mkfs() {
    local _domk=$1
    local _device=$2
    local _fstype=$3
    local _dest=$4
    local _mountpoint=$5

    if [ "${_fstype}" = "swap" ]; then
        _mountpoint="swap"
        swapoff ${_device} >/dev/null 2>&1
        if [ "${_domk}" = "yes" ]; then
            mkswap ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating swap: mkswap ${_device}"
                return 1
            fi
        fi
        swapon ${_device} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error activating swap: swapon ${_device}"
            return 1
        fi
    elif [ "${_fstype}" = "xfs" ]; then
        if [ "${_domk}" = "yes" ]; then
            mkfs.xfs -f ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mkfs.xfs ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t xfs ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    elif [ "${_fstype}" = "jfs" ]; then
        if [ "${_domk}" = "yes" ]; then
            yes | mkfs.jfs ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mkfs.jfs ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t jfs ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    elif [ "${_fstype}" = "reiserfs" ]; then
        if [ "${_domk}" = "yes" ]; then
            yes | mkreiserfs ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mkreiserfs ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t reiserfs ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    elif [ "${_fstype}" = "ext2" ]; then
        if [ "${_domk}" = "yes" ]; then
            mke2fs "${_device}" >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mke2fs ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t ext2 ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    elif [ "${_fstype}" = "ext3" ]; then
        if [ "${_domk}" = "yes" ]; then
            mke2fs -j ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mke2fs -j ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t ext3 ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    elif [ "${_fstype}" = "vfat" ]; then
        if [ "${_domk}" = "yes" ]; then
            mkfs.vfat ${_device} >$LOG 2>&1
            if [ $? != 0 ]; then
                msg "Error creating filesystem: mkfs.vfat ${_device}"
                return 1
            fi
            sleep 2
        fi
        mkdir -p ${_dest}${_mountpoint}
        mount -t vfat ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
        if [ $? != 0 ]; then
            msg "Error mounting ${_dest}${_mountpoint}"
            return 1
        fi
    else
        msg "unknown fstype for ${_device}"
        return 1
    fi

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

    if [ "${_fstype}" = "swap" ]; then
        echo "0" >>/tmp/.fstab
    else
        echo "1" >>/tmp/.fstab
    fi
}

mksimplefs() {
    DEVICE=$1
    FSSPECS=$2
    sfdisk_input=""

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

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

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

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

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

    # swap required
    if [ $(echo $FSSPECS | grep 'swap:' | wc -l) -lt 1 ]; then
        msg "Need at least one swap partition"
        return 1
    fi

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

    if [ $(echo $FSSPECS | grep '/home:' | wc -l) -ne 1 ]; then
        msg "Need exactly one home partition"
        return 1
    fi

    rm -f /tmp/.fstab

    # disable swap and all mounted partitions, umount / last!
    dodialog infobox "Disabling swapspace, unmounting already mounted disk devices..."
    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

    # 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
    dodialog infobox "Partitioning $DEVICE"
    sfdisk $DEVICE -uM >$LOG 2>&1 <<EOF
$sfdisk_input
EOF
    if [ $? -gt 0 ]; then
        msg "Error partitioning $DEVICE (see $LOG for details)"
        prink 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

    msg "Auto-prepare was successful"
    S_MKFSAUTO=1
}

partition() {
    if [ "$S_MKFSAUTO" = "1" ]; then
        msg "You have already prepared your filesystems with Auto-prepare"
        return 0
    fi
    # disable swap and all mounted partitions, umount / last!
    dodialog infobox "Disabling swapspace, unmounting already mounted disk devices..."
    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
    #
    # Select disk to partition
    #
    DISCS=$(finddisks _)
    DISCS="$DISCS OTHER -"
    dodialog msgbox "Available Disks:\n\n$(for i in $(finddisks); do echo -n $(echo $i | sed 's#/dev/##g'): '' ; dmesg | grep $(echo $i | sed 's#/dev/##g') | grep sectors | sort -u | cut -d'(' -f2 | cut -d')' -f1; echo "\n"; done)\n"
    domenu menu "Select the disk you want to partition" 14 55 7 $DISCS 2>$ANSWER || return 1
    DISC=$(cat $ANSWER)
    if [ "$DISC" = "OTHER" ]; then
        dodialog inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>$ANSWER || return 1
        DISC=$(cat $ANSWER)
    fi
    while [ "$DISC" != "DONE" ]; do
        #
        # Partition disc
        #
        dodialog 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

        domenu menu "Select the disk you want to partition" 14 55 7 $DISCS DONE + 2>$ANSWER || return 1
        DISC=$(cat $ANSWER)
        if [ "$DISC" = "OTHER" ]; then
            dodialog inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>$ANSWER || return 1
            DISC=$(cat $ANSWER)
        fi
    done
    S_PART=1
}

mountpoints() {
    if [ "$S_MKFSAUTO" = "1" ]; then
        msg "You have already prepared your filesystems with Auto-prepare"
        return 0
    fi
    while [ "$PARTFINISH" != "DONE" ]; do
    : >/tmp/.fstab
    : >/tmp/.parts

    # Determine which filesystems are available
    insmod /lib/modules/$(uname -r)/kernel/fs/xfs/xfs.ko >/dev/null 2>&1
    insmod /lib/modules/$(uname -r)/kernel/fs/jfs/jfs.ko >/dev/null 2>&1
    FSOPTS="ext2 Ext2 ext3 Ext3"
    [ "$(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.vfat 2>/dev/null)" ]   && FSOPTS="$FSOPTS vfat VFAT"

    #
    # Select mountpoints
    #
    dodialog msgbox "Available Disks:\n\n$(for i in $(finddisks); do echo -n $(echo $i | sed 's#/dev/##g'): '' ; dmesg | grep $(echo $i | sed 's#/dev/##g') | grep sectors | sort -u | cut -d'(' -f2 | cut -d')' -f1; echo "\n"; done)\n"
    PARTS=$(findpartitions _)
    domenu 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")"
    PART_SWAP=$PART
    if [ "$PART_SWAP" != "NONE" ]; then
        DOMKFS="no"
        dodialog yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
        echo "$PART:swap:swap:$DOMKFS" >>/tmp/.parts
    fi

    domenu 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
    domenu menu "Select a filesystem for $PART" 13 45 6 $FSOPTS 2>$ANSWER || return 1
    FSTYPE=$(cat $ANSWER)
    DOMKFS="no"
    dodialog yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
    echo "$PART:$FSTYPE:/:$DOMKFS" >>/tmp/.parts

    #
    # Additional partitions
    #
    domenu 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
        domenu menu "Select a filesystem for $PART" 13 45 6 $FSOPTS 2>$ANSWER || return 1
        FSTYPE=$(cat $ANSWER)
        MP=""
        while [ "${MP}" = "" ]; do
            dodialog inputbox "Enter the mountpoint for $PART" 8 65 "/boot" 2>$ANSWER || return 1
            MP=$(cat $ANSWER)
            if grep ":$MP:" /tmp/.parts; then
                dodialog msgbox "ERROR: You have defined 2 identical mountpoints! Please select another mountpoint." 8 65
                MP=""
            fi
        done
        DOMKFS="no"
        dodialog yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
        echo "$PART:$FSTYPE:$MP:$DOMKFS" >>/tmp/.parts
        domenu menu "Select any additional partitions to mount under your new root" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
        PART=$(cat $ANSWER)
    done
    dodialog 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)" 18 && PARTFINISH="DONE"
    done
    # disable swap and all mounted partitions
    dodialog infobox "Disabling swapspace, unmounting already mounted disk devices..."
    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
    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)
        umount ${DESTDIR}${MP}
        if [ "$DOMKFS" = "yes" ]; then
            if [ "$FSTYPE" = "swap" ]; then
                dodialog infobox "Creating swapspace on $PART, activating..."
            else
                dodialog infobox "Creating $FSTYPE on $PART, mounting to ${DESTDIR}${MP}"
            fi
            _mkfs yes $PART $FSTYPE $DESTDIR $MP || return 1
        else
            if [ "$FSTYPE" = "swap" ]; then
                dodialog infobox "Activating swapspace on $PART"
            else
                dodialog infobox "Mounting $PART to ${DESTDIR}${MP}"
            fi
            _mkfs no $PART $FSTYPE $DESTDIR $MP || return 1
        fi
        sleep 1
    done

    msg "Partitions were successfully mounted."
    S_MKFS=1
}

getsource() {
    if [ "$MODE" = "cd" ]; then
        msg "Packages included on this disk have been mounted to /src/core/pkg. If you wish to use your own packages from another source, manually mount them there."
        if [ ! -d /src/core/pkg ]; then
            msg "Package directory /src/core/pkg is missing!"
            return 1
        fi
        SRC_READY=2
    fi
    if [ "$MODE" = "ftp" ]; then
        dodialog msgbox "Keep in mind ftp.archlinux.org is throttled.\nPlease select another mirror to get full download speed." 18 70
        # FIXME: this regex doesn't honor commenting
        MIRRORS=$(egrep -o '((ftp)|(http))://[^/]*' "${MIRRORLIST}" | sed 's|$| _|g')
        domenu menu "Select an FTP/HTTP mirror" 14 55 7 $MIRRORS "Custom" "_" 2>$ANSWER || return 1
        local _server=$(cat $ANSWER)
        if [ "${_server}" = "Custom" ]; then
            dodialog inputbox "Enter the full URL to core repo." 8 65 "ftp://ftp.archlinux.org/core/os/i686" 2>$ANSWER || return 1
            SYNC_URL=$(cat $ANSWER)
        else
            SYNC_URL=$(egrep -o "${_server}.*" "${MIRRORLIST}" | sed 's/\$repo/core/g')
        fi
        SRC_READY=1
    fi
}

prepare_pacman() {
    # somehow our root can get remounted as RO, which breaks this stage.
    mount -o remount,rw / >/dev/null 2>&1
    if [ "$MODE" = "cd" ]; then
        # Setup a pacman.conf in /tmp
        echo "[core]" >/tmp/pacman.conf
        echo "Server = file:///src/core/pkg" >>/tmp/pacman.conf
        ! [ -d $DESTDIR/var/lib/pacman ] && mkdir -p $DESTDIR/var/lib/pacman
        ! [ -d /var/lib/pacman ] && mkdir -p /var/lib/pacman
        mkdir -p $DESTDIR/var/cache/pacman/pkg /var/cache/pacman >/dev/null 2>&1
        rm -f /var/cache/pacman/pkg >/dev/null 2>&1
        dodialog yesno "Do you want to keep the packages in pacman cache?\nYou can delete them later by running 'pacman -Scc'" "" "" "default=no" || delpkg="yes"
        if [ "$delpkg" = "yes" ]; then
            # set up a symlink to fool pacman so it doesn't copy all the packages to the cache
            ln -sf /src/core/pkg /var/cache/pacman/pkg >/dev/null 2>&1
        else
            ln -sf $DESTDIR/var/cache/pacman/pkg /var/cache/pacman/pkg >/dev/null 2>&1
        fi
    fi

    if [ "$MODE" = "ftp" ]; then
        # Setup a pacman.conf in /tmp
        cat << EOF > /tmp/pacman.conf
[options]
CacheDir = ${DESTDIR}/var/cache/pacman/pkg
CacheDir = /src/core/pkg

[core]
Server = ${SYNC_URL}
EOF
        ! [ -d $DESTDIR/var/lib/pacman ] && mkdir -p $DESTDIR/var/lib/pacman
        ! [ -d /var/lib/pacman ] && mkdir -p /var/lib/pacman
        mkdir -p $DESTDIR/var/cache/pacman/pkg /var/cache/pacman >/dev/null 2>&1
        rm -f /var/cache/pacman/pkg >/dev/null 2>&1
        ln -sf $DESTDIR/var/cache/pacman/pkg /var/cache/pacman/pkg >/dev/null 2>&1
    fi

    dodialog infobox "Refreshing package database..." 6 45
    # FIXME: if sync fails. this function needs to fail.
    $PACMAN -Sy >$LOG 2>&1
}

cleanup_pacman() {
    if [ "$delpkg" = "yes" ]; then
        if [ "$MODE" = "cd" ]; then
            rm -f $DESTDIR/var/cache/pacman/pkg >/dev/null 2>&1
        fi
    fi
}

selectpkg() {
    if [ $SRC_READY -gt 0 -a "$MODE" = "ftp" ]; then
        dodialog yesno "Would you like to select a different server?"
        if [ $? -eq 0 ]; then
            getsource || return 1
        fi
    else
        getsource || return 1
    fi

    dodialog 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 with your categories already selected, allowing you to fine-tune.\n\nNOTE: The BASE category is always installed, and its packages will not appear in this menu." 18 70

    # sync up so we can get package lists
    prepare_pacman

    # category selection hasn't been done before
    if ! [ -f /tmp/.pkgcategory ]; then
        CATLIST=""
        for i in $($PACMAN -Sg | sed "s/^base$/ /g"); do
            CATLIST="${CATLIST} ${i} - OFF"
        done
    else
    # category selection was already run at least once
        CATLIST=""
        for i in $(cat /tmp/.pkgcategory | sed 's|\"||g'); do
            CATLIST="$CATLIST $i ^ ON"
        done
        for i in $($PACMAN -Sg | sed "s/^base$/ /g"); do
            grep $i /tmp/.pkgcategory > /dev/null 2>&1 || CATLIST="$CATLIST $i - OFF"
        done
    fi
    domenu checklist "Select Package Categories" 19 55 12 $CATLIST 2>/tmp/.pkgcategory || return 1
    
    # mash up the package lists
    COREPKGS=$($PACMAN -Sl core | cut -d' ' -f2)

    # remove base packages from the selectable list
    for i in $($PACMAN -Sg base | tail +2); do
        COREPKGS=$(echo ${COREPKGS} | sed "s/\(^${i} \| ${i} \| ${i}$\)/ /g")
    done
    # assemble a list of pre-selected packages
    for i in $(cat /tmp/.pkgcategory | sed 's|"||g'); do
        CATPKGS="$CATPKGS $($PACMAN -Sg ${i} | tail +2)"
    done
    # put together the menu list
    PKGLIST=""
    for i in ${COREPKGS}; do
        # if the package was preselected, check it
        if [ -n "$(echo $CATPKGS | grep "\(^${i} \| ${i} \| ${i}$\)")" ]; then
            PKGLIST="$PKGLIST ${i} ^ ON"
        else
            PKGLIST="$PKGLIST ${i} - OFF"
        fi
    done
    domenu checklist "Select Packages To Install." 19 60 12 $PKGLIST 2>/tmp/.pkglist || return 1
    S_SELECT=1
}

doinstall()
{
    # begin install
    rm -f /tmp/pacman.log
    # all pacman output goes to /tmp/pacman.log, which we tail into a dialog
    ( \
        echo "Installing Packages..." >/tmp/pacman.log ; echo >>/tmp/pacman.log ; \
        touch /tmp/setup-pacman-running ; \
        $PACMAN -S $(echo $* | sed 's|"||g') >>/tmp/pacman.log 2>&1 ; \
        echo $? >/tmp/.pacman.retcode; \
        echo >>/tmp/pacman.log; \

        if [ "$(cat /tmp/.pacman.retcode)" -gt 0 ]; then
            echo "Package Installation FAILED." >>/tmp/pacman.log
        else
            echo "Package Installation Complete." >>/tmp/pacman.log
        fi
        rm /tmp/setup-pacman-running
    ) &

    sleep 2
    dialog --backtitle "$TITLE" --title " Installing... Please Wait " \
    --no-kill --tailboxbg "/tmp/pacman.log" 18 70 2>/tmp/.pid
    while [ -f /tmp/setup-pacman-running ]; do
        sleep 1
    done
    kill $(cat /tmp/.pid)
    if [ "$(cat /tmp/.pacman.retcode)" -gt 0 ]; then
        result="Installation Failed (see errors below)"
        retcode=1
    else
        result="Installation Complete"
        retcode=0
    fi
    # disabled for now
    #dialog --backtitle "$TITLE" --title " $result " \
    #   --exit-label "Continue" --textbox "/tmp/pacman.log" 18 70
    # fix the stair-stepping that --tailboxbg leaves us with
    stty onlcr

    rm -f /tmp/.pacman.retcode
    return $retcode
}

installpkg() {
    if [ ! -f /tmp/.pkglist -o "$S_SELECT" != "1" ]; then
        msg "You must select packages first."
        return 1
    fi
    if [ "$S_MKFS" != "1" -a "$S_MKFSAUTO" != "1" ]; then
        getdest
    fi

    msg "Package installation will begin now.  You can watch the output in the progress window. Please be patient."
    delpkg="no"
    LIST="base" # always install base
    for pkg in $(cat /tmp/.pkglist); do
        LIST="$LIST $pkg"
    done

    prepare_pacman
    if [ "$MODE" = "cd" ]; then
        # mount proc/sysfs first, so mkinitrd can use auto-detection if it wants
        ! [ -d $DESTDIR/proc ] && mkdir $DESTDIR/proc
        ! [ -d $DESTDIR/sys ] && mkdir $DESTDIR/sys
        ! [ -d $DESTDIR/dev ] && mkdir $DESTDIR/dev
        mount -t proc none $DESTDIR/proc
        mount -t sysfs none $DESTDIR/sys
        mount -o bind /dev $DESTDIR/dev
        doinstall $LIST
        dialog --backtitle "$TITLE" --title " $result " \
            --exit-label "Continue" --textbox "/tmp/pacman.log" 18 70
        if [ $? -gt 0 ]; then
            cleanup_pacman
            return 1
        fi
        S_INSTALL=1
    fi

    if [ "$MODE" = "ftp" ]; then
        dodialog yesno "Do you want to keep the downloaded packages?  You can delete them later by running 'pacman -Scc'" || delpkg="yes"
        dodialog infobox "Downloading packages.  See $LOG for output." 6 55
        $PACMAN -Sw $(echo $LIST | sed 's|"||g') >$LOG 2>&1
        if [ $? -gt 0 ]; then
            dodialog msgbox "One or more packages failed to download.  You can try again by re-selecting Install Packages from the main menu." 12 65
            return 1
        fi
        # mount proc/sysfs first, so mkinitrd can use auto-detection if it wants
        ! [ -d $DESTDIR/proc ] && mkdir $DESTDIR/proc
        ! [ -d $DESTDIR/sys ] && mkdir $DESTDIR/sys
        ! [ -d $DESTDIR/dev ] && mkdir $DESTDIR/dev
        mount -t proc none $DESTDIR/proc
        mount -t sysfs none $DESTDIR/sys
        mount -o bind /dev $DESTDIR/dev
        doinstall $LIST
        dialog --backtitle "$TITLE" --title " $result " \
            --exit-label "Continue" --textbox "/tmp/pacman.log" 18 70
        if [ $? -gt 0 ]; then
            cleanup_pacman
            return 1
        fi
        S_INSTALL=1
        if [ "$S_INSTALL" = "1" -a "$delpkg" = "yes" ]; then
            # clean up the cached package files that pacman leaves
            $PACMAN -Scc >$LOG 2>&1
        fi
    fi
    umount $DESTDIR/proc $DESTDIR/sys $DESTDIR/dev
    sync
    # 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

    cleanup_pacman
}

donetwork() {
    INTERFACE=
    S_DHCP=
    ifaces=$(ifconfig -a | egrep "Ethernet" | cut -d' ' -f1 | sed 's|$| _|g')
    if [ "$ifaces" = "" ]; then
        dodialog yesno "Cannot find any ethernet interfaces. You probably haven't loaded\nyour network module yet.  You have two options:\n\n  1) Probe for the correct module now.\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
            probenic
            if [ $? -gt 0 ]; then
                return 1
            fi
        fi
        ifaces=$(ifconfig -a | egrep "Ethernet" | cut -d' ' -f1 | sed 's|$| _|g')
        if [ "$ifaces" = "" ]; then
            msg "No network interfaces available."
            return 1
        fi
    fi
    while [ "$INTERFACE" = "" ]; do
        dodialog msgbox "Available Ethernet Interfaces:\n$(ifconfig -a | egrep "Ethernet" | sed 's# #_#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"
        dialog --backtitle "$TITLE" --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) ;;
            *) probenic ;;
        esac
        ifaces=$(ifconfig -a | egrep "Ethernet" | cut -d' ' -f1 | sed 's|$| _|g')
    done
    dodialog yesno "Do you want to use DHCP?"
    if [ $? -eq 0 ]; then
        dodialog infobox "Please wait.  Polling for DHCP server on $INTERFACE..."
        dhcpcd $INTERFACE >$LOG 2>&1 || msg "Failed to run dhcpcd." || return 1
        sleep 10
        if [ ! $(ifconfig $INTERFACE | grep 'inet addr:') ]; then
            msg "DHCP request failed." || return 1
        fi
        S_DHCP=1
    else
        NETPARAMETERS=""
        while [ "$NETPARAMETERS" = "" ]; do
            dodialog inputbox "Enter your IP address" 8 65 "192.168.0.2" 2>$ANSWER || return 1
            IPADDR=$(cat $ANSWER)
            dodialog inputbox "Enter your netmask" 8 65 "255.255.255.0" 2>$ANSWER || return 1
            SUBNET=$(cat $ANSWER)
            dodialog inputbox "Enter your broadcast" 8 65 "192.168.0.255" 2>$ANSWER || return 1
            BROADCAST=$(cat $ANSWER)
            dodialog inputbox "Enter your gateway (optional)" 8 65 "192.168.0.1" 8 65 2>$ANSWER || return 1
            GW=$(cat $ANSWER)
            dodialog inputbox "Enter your DNS server IP" 8 65 "192.168.0.1" 2>$ANSWER || return 1
            DNS=$(cat $ANSWER)
            dodialog 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)
            dodialog 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)
            dodialog 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"
            case $? in
                1) ;;
                0) NETPARAMETERS="1" ;;
            esac
        done
        ifconfig $INTERFACE $IPADDR netmask $SUBNET broadcast $BROADCAST up >$LOG 2>&1 || msg "Failed to setup $INTERFACE interface." || return 1
        if [ "$GW" != "" ]; then
            route add default gw $GW >$LOG 2>&1 || msg "Failed to setup your gateway." || 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
    msg "The network is configured."
    S_NET=1
}

probenic() {
    workdir="$PWD"
    dodialog infobox "Looking for a matching ethernet module.  Please wait..."
    printk off

    cd /lib/modules/$(uname -r)/kernel/drivers/net
    if [ $? -gt 0 ]; then
        msg "No ethernet modules were found!"
        printk on
        cd "$workdir"
        return 1
    fi
    # 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

    ifconfig -a | egrep "Ethernet" >/dev/null 2>&1
    if [ $? -gt 0 ]; then
        msg "No matching ethernet modules found."
    else
        msg "Probe succeeded.  Your network module is loaded."
    fi

    printk on
    cd "$workdir"
}

dolilo() {
    if [ ! -f $DESTDIR/etc/lilo.conf ]; then
        msg "Error: Couldn't find $DESTDIR/etc/lilo.conf.  Is LILO installed?"
        return 1
    fi
    # Try to auto-configure LILO...
    if [ "$PART_ROOT" != "" -a "$S_LILO" != "1" ]; then
        sed -i "s|vmlinuz26|vmlinuz|g" $DESTDIR/etc/lilo.conf
        sed -i "s|vmlinuz|$VMLINUZ|g" $DESTDIR/etc/lilo.conf
        local _rootpart="${PART_ROOT}"
        local _uuid="$(getuuid ${PART_ROOT})"
        if [ -n "${_uuid}" ]; then
            _rootpart="/dev/disk/by-uuid/${_uuid}"
        fi
        sed -i "s|root=.*$|root=${_rootpart}|g" $DESTDIR/etc/lilo.conf
    fi
    DEVS=$(finddisks _)
    DEVS="$DEVS $(findpartitions _)"
    if [ "$DEVS" = "" ]; then
        msg "No hard drives were found"
        return 1
    fi
    domenu 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
    msg "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."
    [ "$EDITOR" ] || geteditor
    $EDITOR ${DESTDIR}/etc/lilo.conf
    dodialog infobox "Installing the LILO bootloader..."
    mount -t proc none $DESTDIR/proc
    mount -o bind /dev $DESTDIR/dev
    chroot $DESTDIR /sbin/lilo >$LOG 2>&1
    if [ $? -gt 0 ]; then
        umount $DESTDIR/dev $DESTDIR/proc
        msg "Error installing LILO. (see $LOG for output)"
        return 1
    fi
    umount $DESTDIR/dev $DESTDIR/proc
    msg "LILO was successfully installed."
    S_LILO=1
}

dogrub() {
    get_grub_map
    if [ ! -f $DESTDIR/boot/grub/menu.lst ]; then
        msg "Error: Couldn't find $DESTDIR/boot/grub/menu.lst.  Is GRUB installed?"
        return 1
    fi
    # try to auto-configure GRUB...
    if [ "$PART_ROOT" != "" -a "$S_GRUB" != "1" ]; then
        grubdev=$(mapdev $PART_ROOT)
        local _rootpart="${PART_ROOT}"
        local _uuid="$(getuuid ${PART_ROOT})"
        if [ -n "${_uuid}" ]; then
            _rootpart="/dev/disk/by-uuid/${_uuid}"
        fi
        # look for a separately-mounted /boot partition
        bootdev=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
        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
            echo "" >>$DESTDIR/boot/grub/menu.lst
            echo "# (0) Arch Linux" >>$DESTDIR/boot/grub/menu.lst
            echo "title  Arch Linux" >>$DESTDIR/boot/grub/menu.lst
            subdir=
            if [ "$bootdev" != "" ]; then
                grubdev=$(mapdev $bootdev)
            else
                subdir="/boot"
            fi
            echo "root   $grubdev" >>$DESTDIR/boot/grub/menu.lst
            echo "kernel $subdir/$VMLINUZ root=${_rootpart} ro" >>$DESTDIR/boot/grub/menu.lst
            if [ "$VMLINUZ" = "vmlinuz26" ]; then
                echo "initrd $subdir/kernel26.img" >>$DESTDIR/boot/grub/menu.lst
            fi
            echo "" >>$DESTDIR/boot/grub/menu.lst
            # adding fallback/full image
            echo "# (1) 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
            echo "kernel $subdir/$VMLINUZ root=${_rootpart} ro" >>$DESTDIR/boot/grub/menu.lst
            if [ "$VMLINUZ" = "vmlinuz26" ]; then
                echo "initrd $subdir/kernel26-fallback.img" >>$DESTDIR/boot/grub/menu.lst
            fi
            echo "" >>$DESTDIR/boot/grub/menu.lst
            echo "# (1) 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

    msg "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."
    [ "$EDITOR" ] || geteditor
    $EDITOR ${DESTDIR}/boot/grub/menu.lst

    DEVS=$(finddisks _)
    DEVS="$DEVS $(findpartitions _)"
    if [ "$DEVS" = "" ]; then
        msg "No hard drives were found"
        return 1
    fi
    domenu menu "Select the boot device where the GRUB bootloader will be installed (usually the MBR)" 14 55 7 $DEVS 2>$ANSWER || return 1
    ROOTDEV=$(cat $ANSWER)
    dodialog infobox "Installing the GRUB bootloader..."
    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
        /usr/sbin/xfs_freeze -f $DESTDIR/boot > /dev/null 2>&1
        /usr/sbin/xfs_freeze -f $DESTDIR/ > /dev/null 2>&1
    fi
    # look for a separately-mounted /boot partition
    bootpart=$(mount | grep $DESTDIR/boot | cut -d' ' -f 1)
    if [ "$bootpart" = "" ]; then
        if [ "$PART_ROOT" = "" ]; then
            dodialog inputbox "Enter the full path to your root device" 8 65 "/dev/sda3" 2>$ANSWER || return 1
            bootpart=$(cat $ANSWER)
        else
            bootpart=$PART_ROOT
        fi
    fi
    dodialog yesno "Do you have your system installed on software raid?\nAnswer 'YES' to install grub to another hard disk."  "" "" "default=no"
    if [ $? -eq 0 ]; then
        domenu menu "Please select the boot partition device, this cannot be autodetected!\nPlease redo grub installation for all partitions you need it!" 14 55 7 $DEVS 2>$ANSWER || return 1
        bootpart=$(cat $ANSWER)
    fi
    bootpart=$(mapdev $bootpart)
    bootdev=$(mapdev $ROOTDEV)
    if [ "$bootpart" = "" ]; then
        msg "Error: Missing/Invalid root device: $bootpart"
        return 1
    fi
    $DESTDIR/sbin/grub --no-floppy --batch >/tmp/grub.log 2>&1 <<EOF
root $bootpart
setup $bootdev
quit
EOF
    cat /tmp/grub.log >$LOG
    # unfreeze xfs filesystems
    if [ -x /usr/sbin/xfs_freeze ]; then
        /usr/sbin/xfs_freeze -u $DESTDIR/boot > /dev/null 2>&1
        /usr/sbin/xfs_freeze -u $DESTDIR/ > /dev/null 2>&1
    fi

    if grep "Error [0-9]*: " /tmp/grub.log >/dev/null; then
        msg "Error installing GRUB. (see $LOG for output)"
        return 1
    fi
    msg "GRUB was successfully installed."
    S_GRUB=1
}

mainmenu() {
    if [ -n "$NEXTITEM" ]; then
        DEFAULT="--default-item $NEXTITEM"
    else
        DEFAULT=""
    fi
    if [ "$MODE" = "ftp" ]; then
        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." 15 55 8 \
            "0" "Configure Network" \
            "1" "Prepare Hard Drive" \
            "2" "Select Packages" \
            "3" "Install Packages" \
            "4" "Configure System" \
            "5" "Install Bootloader" \
            "6" "Exit Install" 2>$ANSWER
    else
        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." 15 55 8 \
            "1" "Prepare Hard Drive" \
            "2" "Select Packages" \
            "3" "Install Packages" \
            "4" "Configure System" \
            "5" "Install Bootloader" \
            "6" "Exit Install" 2>$ANSWER
    fi
    NEXTITEM="$(cat $ANSWER)"
    case $(cat $ANSWER) in
        "0")
            donetwork ;;
        "1")
            S_MKFSAUTO=0
            S_MKFS=0
            DONE=0
            NEXTITEM=""
            while [ "$DONE" = "0" ]; do
                if [ -n "$NEXTITEM" ]; then
                    DEFAULT="--default-item $NEXTITEM"
                else
                    DEFAULT=""
                fi
                dialog $DEFAULT --backtitle "$TITLE" --menu "Prepare Hard Drive" 12 60 5 \
                    "1" "Auto-Prepare (erases the ENTIRE hard drive)" \
                    "2" "Partition Hard Drives" \
                    "3" "Set Filesystem Mountpoints" \
                    "4" "Return to Main Menu" 2>$ANSWER
                NEXTITEM="$(cat $ANSWER)"
                case $(cat $ANSWER) in
                    "1")
                        DISCS=$(finddisks)
                        if [ $(echo $DISCS | wc -w) -gt 1 ]; then
                            dodialog msgbox "Available Disks:\n\n$(for i in $(finddisks); do dmesg | grep $(echo $i | sed 's#/dev/##g') | grep sectors | sort -u | cut -d')' -f1 |sed -e 's/ /|/g' -e 's/SCSI|device|//g' -e 's/(//g'; done)\n"
                            domenu menu "Select the hard drive to use" 14 55 7 $(finddisks _) 2>$ANSWER || return 1
                            DISC=$(cat $ANSWER)
                        else
                            DISC=$DISCS
                        fi
                            SET_DEFAULTFS=""
                            BOOT_PART_SET=""
                            SWAP_PART_SET=""
                            ROOT_PART_SET=""
                            CHOSEN_FS=""
                            DISC_SIZE=$(dmesg | grep $(echo $DISC | sed 's#/dev/##g') | grep sectors | sort -u | cut -d'(' -f2 | sed -e 's# .*##g')
                            while [ "$SET_DEFAULTFS" = "" ]; do
                                FSOPTS="ext2 Ext2 ext3 Ext3"
                                [ "$(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
                                    dodialog inputbox "Enter the size (MegaByte/MB) of your /boot partition,\n(minimum value is 16).\n\nDisk space left: $DISC_SIZE (MegaByte/MB)" 8 65 "32" 2>$ANSWER || return 1
                                    BOOT_PART_SIZE="$(cat $ANSWER)"
                                    if [ "$BOOT_PART_SIZE" = ""  ]; then
                                        dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                    else
                                        if [ "$BOOT_PART_SIZE" -ge "$DISC_SIZE" -o "$BOOT_PART_SIZE" -lt "16" -o "$SBOOT_PART_SIZE" = "$DISC_SIZE" ]; then
                                            dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                        else
                                            BOOT_PART_SET=1
                                        fi
                                    fi
                                done
                                DISC_SIZE=$(($DISC_SIZE-$BOOT_PART_SIZE))
                                while [ "$SWAP_PART_SET" = "" ]; do
                                    dodialog inputbox "Enter the size (MegaByte/MB) of your swap partition,\n(minimum value is > 0).\n\nDisk space left: $DISC_SIZE (MegaByte/MB)" 8 65 "256" 2>$ANSWER || return 1
                                    SWAP_PART_SIZE=$(cat $ANSWER)
                                    if [ "$SWAP_PART_SIZE" = "" -o  "$SWAP_PART_SIZE" = "0" ]; then
                                        dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                    else
                                        if [ "$SWAP_PART_SIZE" -ge "$DISC_SIZE" ]; then
                                            dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                        else
                                            SWAP_PART_SET=1
                                        fi
                                    fi
                                done
                                DISC_SIZE=$(($DISC_SIZE-$SWAP_PART_SIZE))
                                while [ "$ROOT_PART_SET" = "" ]; do
                                    dodialog inputbox "Enter the size (MegaByte/MB) of your / partition,\nthe /home partition will take all the left space.\n\nDisk space left:  $DISC_SIZE (MegaByte/MB)" 8 65 "7500" 2>$ANSWER || return 1
                                    ROOT_PART_SIZE=$(cat $ANSWER)
                                    if [ "$ROOT_PART_SIZE" = "" -o "$ROOT_PART_SIZE" = "0" ]; then
                                        dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                    else
                                        if [ "$ROOT_PART_SIZE" -ge "$DISC_SIZE" ]; then
                                            dodialog msgbox "ERROR: You have entered a wrong size, please enter again."
                                        else
                                            dodialog yesno "$(($DISC_SIZE-$ROOT_PART_SIZE)) (MegaByte/MB) will be used for your /home partition?" "" "" && ROOT_PART_SET=1
                                        fi
                                    fi
                                done
                                while [ "$CHOSEN_FS" = "" ]; do
                                    domenu menu "Select a filesystem for / and /home" 13 45 6 $FSOPTS 2>$ANSWER || return 1
                                    FSTYPE=$(cat $ANSWER)
                                    dodialog yesno "$FSTYPE will be used for / and /home?" "" "" && 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")
                        dodialog yesno "$DISC will be COMPLETELY ERASED!  Are you absolutely sure?" "" "" "default=no" \
                            && mksimplefs $DISC "$REAL_DEFAULTFS" ;;
                    "2")
                        partition ;;
                    "3")
                        PARTFINISH=""
                        mountpoints ;;
                    *)
                        DONE=1 ;;
                esac
            done
            NEXTITEM="1" ;;
        "2")
            selectpkg ;;
        "3")
            installpkg ;;
        "4")
            HWDETECT=""
            HWPARAMETER=""
            DSDT_ENABLE=""
            dodialog 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 controllers,\nnetwork and sound devices.\n\nIt is recommended to say 'YES' here." 18 70 && HWDETECT="yes"
            if [ "$HWDETECT" = "yes" ]; then
                if /usr/bin/vmware-detect; then
                    HWPARAMETER="$HWPARAMETER --vmware"
                fi
                grep -qw ide-legacy /proc/cmdline && HWPARAMETER="$HWPARAMETER --ide-legacy"
                dodialog yesno "Do you need support for booting from usb devices?" "" "" default=no && HWPARAMETER="$HWPARAMETER --usb"
                dodialog yesno "Do you need support for booting from firewire devices?" "" "" default=no && HWPARAMETER="$HWPARAMETER --fw"
                dodialog yesno "Do you need support for booting from pcmcia devices?" "" "" default=no && HWPARAMETER="$HWPARAMETER --pcmcia"
                dodialog yesno "Do you need support for booting from nfs shares?" "" "" default=no && HWPARAMETER="$HWPARAMETER --nfs"
                dodialog yesno "Do you need support for booting from software raid arrays?" "" "" default=no  && HWPARAMETER="$HWPARAMETER --raid"
                if [ -e $DESTDIR/lib/initcpio/hooks/raid-partitions ]; then
                    dodialog yesno "Do you need support for booting from software raid mdp/partition arrays?" "" "" default=no  && HWPARAMETER="$HWPARAMETER --raid-partitions"
                fi
                dodialog yesno "Do you need support for booting from lvm2 volumes?" "" "" default=no && HWPARAMETER="$HWPARAMETER --lvm2"
                dodialog yesno "Do you need support for booting from encrypted volumes?" "" "" default=no && HWPARAMETER="$HWPARAMETER --encrypt"
                dodialog yesno "Do you need support for booting the kernel with a custom DSDT file?" "" "" default=no && DSDT_ENABLE=1
                if [ "$DSDT_ENABLE" = "1" ]; then
                    while [ "$DSDT" = "" ]; do
                        dodialog inputbox "Enter the custom DSDT file (with full path)" 8 65 "" 2>$ANSWER || return 1
                        DSDT=$(cat $ANSWER)
                        if [ -s "$DSDT" ]; then
                            cp $DSDT $DESTDIR/lib/initcpio/custom.dsdt
                            HWPARAMETER="$HWPARAMETER --dsdt"
                        else
                            dodialog msgbox "ERROR: You have entered a wrong file name, please enter again."
                            DSDT=""
                        fi
                    done
                fi
                # add always keymap
                HWPARAMETER="$HWPARAMETER --keymap"
                HWDETECTHOSTCONTROLLER=""
                HWDETECTHOOKS=""
                HWDETECTRC=""
                HWDETECTHOSTCONTROLLER="$(hwdetect --hostcontroller $HWPARAMETER)"
                HWDETECTHOOKS="$(hwdetect --hooks-dir=$DESTDIR/lib/initcpio/install --hooks $HWPARAMETER)"
                HWDETECTRC="$(echo $(hwdetect --net --sound $HWPARAMETER)| sed -e 's#.*) ##g')"
                [ -n "$HWDETECTHOSTCONTROLLER" ] && sed -i -e "s/^MODULES=.*/$HWDETECTHOSTCONTROLLER/g" ${DESTDIR}/etc/mkinitcpio.conf
                [ -n "$HWDETECTHOOKS" ] && sed -i -e "s/^HOOKS=.*/$HWDETECTHOOKS/g" ${DESTDIR}/etc/mkinitcpio.conf
                [ -n "$HWDETECTRC" ] && sed -i -e "s/^MODULES=.*/$HWDETECTRC/g" ${DESTDIR}/etc/rc.conf
                # fallback modifications
                #USE_HWDETECT_RESULTS=""
                #dodialog yesno "PRECONFIGURATION?\n-----------------\n\nDo you want to use 'hwdetect' results from Configuration dialog \nfor /etc/mkinitcpio.d/kernel26-fallback.conf?\n\nThis ensures consistent ordering of your hard disk controllers.\n\nIt is recommended to say 'YES' here." 18 70 && USE_HWDETECT_RESULTS="yes"
                #if [ "$USE_HWDETECT_RESULTS" = "yes" ]; then
                #   [ -n "$HWDETECTHOSTCONTROLLER" ] && sed -i -e "s/^MODULES=.*/$HWDETECTHOSTCONTROLLER/g" ${DESTDIR}/etc/mkinitcpio.d/kernel26-fallback.conf
                #   HWDETECTHOOK="$(echo $HWDETECTHOOKS | sed -e 's/autodetect\ //g')"
                #   [ -n "$HWDETECTHOOK" ] && sed -i -e "s/^HOOKS=.*/$HWDETECTHOOK/g" ${DESTDIR}/etc/mkinitcpio.d/kernel26-fallback.conf
                #fi
            fi
            if [ -s /tmp/.keymap ]; then
                dodialog yesno "Do you want to use the keymap: $(cat /tmp/.keymap | sed -e 's/\..*//g') in rc.conf?" "" "" && sed -i -e "s/^KEYMAP=.*/KEYMAP=\"$(cat /tmp/.keymap | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
            fi
            if [ -s /tmp/.font ]; then
                dodialog yesno "Do you want to use the consolefont: $(cat /tmp/.font | sed -e 's/\..*//g') in rc.conf?" "" "" && sed -i -e "s/^CONSOLEFONT=.*/CONSOLEFONT=\"$(cat /tmp/.font | sed -e 's/\..*//g')\"/g" ${DESTDIR}/etc/rc.conf
            fi
            if [ "$S_NET" = "1" ]; then
                dodialog 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" "" "" && (
                if [ "$S_DHCP" != "1" ]; then
                    sed -i -e "s#eth0=\"eth0#$INTERFACE=\"$INTERFACE#g" ${DESTDIR}/etc/rc.conf
                    sed -i -e "s# 192.168.0.2 # $IPADDR #g" ${DESTDIR}/etc/rc.conf
                    sed -i -e "s# 255.255.255.0 # $SUBNET #g" ${DESTDIR}/etc/rc.conf
                    sed -i -e "s# 192.168.0.255\"# $BROADCAST\"#g" ${DESTDIR}/etc/rc.conf
                    sed -i -e "s#eth0)#$INTERFACE)#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#eth0=\"eth0.*#$INTERFACE=\"dhcp\"#g" ${DESTDIR}/etc/rc.conf
                fi
                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)
            fi
            [ "$EDITOR" ] || geteditor
            DONE=0
            FILE=""
            while [ "$EDITOR" != "" -a "$DONE" = "0" ]; do
                if [ -n "$FILE" ]; then
                    DEFAULT="--default-item $FILE"
                else
                    DEFAULT=""
                fi
                dialog $DEFAULT --backtitle "$TITLE" --menu "Configuration" 17 80 10 \
                    "/etc/rc.conf" "System Config" \
                    "/etc/fstab" "Filesystem Mountpoints" \
                    "/etc/mkinitcpio.conf" "Initramfs Config" \
                    "/etc/modprobe.conf" "Kernel Modules (for 2.6.x)" \
                    "/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" \
                    "Root-Password" "Set the root password" \
                    "Pacman-Mirror" "Set the primary pacman mirror" \
                    "_" "Return to Main Menu" 2>$ANSWER
                FILE=$(cat $ANSWER)

                if [ "$FILE" = "_" -o "$FILE" = "" ]; then
                    mount -t proc none $DESTDIR/proc
                    mount -t sysfs none $DESTDIR/sys
                    mount -o bind /dev $DESTDIR/dev
                    # all pacman output goes to /tmp/pacman.log, which we tail into a dialog
                    ( \
                    touch /tmp/setup-mkinitcpio-running
                    echo "Initramfs progress ..." > /tmp/initramfs.log; echo >> /tmp/initramfs.log
                    chroot $DESTDIR /sbin/mkinitcpio -p kernel26 >>/tmp/initramfs.log 2>&1
                    echo >> /tmp/initramfs.log
                    rm -f /tmp/setup-mkinitcpio-running
                    ) &
                    sleep 2
                    dialog --backtitle "$TITLE" --title "Rebuilding initramfs images ..." --no-kill --tailboxbg "/tmp/initramfs.log" 18 70
                    while [ -f /tmp/setup-mkinitcpio-running ]; do
                        sleep 1
                    done
                    umount $DESTDIR/proc $DESTDIR/sys $DESTDIR/dev
                    DONE=1
                else
                    if [ "$FILE" = "/etc/mkinitcpio.conf" ]; then
                        dodialog 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=""
                    fi
                    #if [ "$FILE" = "/etc/mkinitcpio.d/kernel26-fallback.conf" ]; then
                    #   dodialog msgbox "The kernel26-fallback.conf file controls which modules will be placed into the fallback 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=""
                    #fi
                    if ! [ "$FILE" = "Root-Password" -o "$FILE" = "Pacman-Mirror" ]; then
                        if [ "$FILE" = "/etc/locale.gen" ]; then
                        # 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
                        fi
                            $EDITOR ${DESTDIR}${FILE}
                    else
                        if [ "$FILE" = "Root-Password" ]; then
                            ROOTPW=""
                            while [ "$ROOTPW" = "" ]; do
                            chroot ${DESTDIR} passwd root && ROOTPW=1
                            done
                        else
                            SAMEMIRROR=""
                            if [ "$MODE" = "ftp" -a "${SYNC_URL}" != "" ]; then
                                dodialog yesno "Would you like to use the same MIRROR you used for installation?" && SAMEMIRROR="yes"
                            fi
                                for i in ${DESTDIR}/etc/pacman.d/*; do
                                    sed -i -e 's/^#Server/Server/g' $i
                                done
                            if ! [ "$SAMEMIRROR" = "yes" ]; then
                                dodialog 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
                                PAC_MIRRORS=$(cat ${DESTDIR}/etc/pacman.d/mirrorlist | cut -d' ' -f3 | grep ^[a-z] | cut -d'/' --fields="1 2 3" | sed 's|$| _|g')
                                domenu 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
                                    dodialog inputbox "Enter the server hostname/ip" 8 65 "ftp://ftp.server.org" 2>$ANSWER || return 1
                                    PAC_SYNC_SERVER=$(cat $ANSWER)
                                    if [ "$(uname -m)" = "x86_64" ]; then
                                            dodialog inputbox "Enter the path to Arch Linux packages" 8 65 "/core/os/x86_64" 2>$ANSWER || return 1
                                    else
                                        dodialog inputbox "Enter the path to Arch Linux packages" 8 65 "/core/os/i686" 2>$ANSWER || return 1
                                    fi
                                    PAC_SYNC_SERVER=$PAC_SYNC_SERVER$(cat $ANSWER)
                                    for i in ${DESTDIR}/etc/pacman.d/*; do
                                    sed -i -e 's/^Server/#Server/g' $i
                                    echo "# Setup-Entry" >> $i
                                    REAL_CUSTOM_PAC_SYNC_SERVER=$(echo $PAC_SYNC_SERVER | sed -e "s#/core/#/\$repo/#g")
                                    echo Server = $REAL_CUSTOM_PAC_SYNC_SERVER >> $i
                                    done
                                else
                                    for i in ${DESTDIR}/etc/pacman.d/*; do
                                    REAL_PAC_SYNC_SERVER="$(grep -m 1 $PAC_SYNC_SERVER $i)"
                                    sed -i -e 's/^Server/#Server/g' $i
                                    echo "# Setup-Entry" >> $i
                                    echo $REAL_PAC_SYNC_SERVER >> $i
                                    done

                                fi
                            else
                                for i in ${DESTDIR}/etc/pacman.d/*; do
                                    PAC_SYNC_SERVER="${SYNC_URL}"
                                    sed -i -e 's/^Server/#Server/g' $i
                                    echo "# Setup-Entry" >> $i
                                    REAL_PAC_SYNC_SERVER=$(echo $PAC_SYNC_SERVER | sed -e "s#/core/#/\$repo/#g")
                                    echo Server = $REAL_PAC_SYNC_SERVER >> $i
                                done
                            fi
                        fi
                    fi
                    if [ "$FILE" = "/etc/locale.gen" ]; then
                        chroot ${DESTDIR} locale-gen
                    fi
                    if [ "$FILE" = "/etc/mkinitcpio.conf" ]; then
                        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
                            dodialog msgbox "ERROR: Detected error in 'HOOKS=' line, please correct HOOKS= in /etc/mkinitcpio.conf!" 18 70
                        fi
                    fi
                    #if [ "$FILE" = "/etc/mkinitcpio.d/kernel26-fallback.conf" ]; then
                    #   for i in $(cat ${DESTDIR}/etc/mkinitcpio.d/kernel26-fallback.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
                    #       dodialog msgbox "ERROR: Detected error in 'HOOKS=' line, please correct HOOKS= in /etc/mkinitcpio.d/kernel26-fallback.conf!" 18 70
                    #   fi
                    #fi
                    if [ "$FILE" = "/etc/rc.conf" ]; then
                        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
                        eval $(grep "^HARDWARECLOCK" ${DESTDIR}/etc/rc.conf)
                        if [ "$HARDWARECLOCK" = "UTC" ]; then
                            chroot ${DESTDIR} /sbin/hwclock --directisa --utc --hctosys
                        else
                            chroot ${DESTDIR} /sbin/hwclock --directisa --localtime --hctosys
                        fi
                        # ugly hack:
                        for line in $(sort --reverse -t: -k3 /tmp/.parts); do
                            PART=$(echo $line | cut -d: -f 1)
                            FSTYPE=$(echo $line | cut -d: -f 2)
                            MP=$(echo $line | cut -d: -f 3)
                            if [ "$MP" != "swap" ]; then
                                umount ${DESTDIR}${MP}
                            fi
                        done
                        for line in $(sort -t: -k3 /tmp/.parts); do
                            PART=$(echo $line | cut -d: -f 1)
                            FSTYPE=$(echo $line | cut -d: -f 2)
                            MP=$(echo $line | cut -d: -f 3)
                            if [ "$MP" != "swap" ]; then
                            mount -t ${FSTYPE} ${PART} ${DESTDIR}${MP}
                            fi
                        done
                        # end of hack
                    fi
                fi
            done ;;
        "5")
            dialog --backtitle "$TITLE" --menu "Which bootloader would you like to use?  Grub is the Arch default.\n\n" \
                10 55 2 \
                "GRUB" "Use the GRUB bootloader (default)" \
                "LILO" "Use the LILO bootloader" 2>$ANSWER
            case $(cat $ANSWER) in
                "GRUB") dogrub ;;
                "LILO") dolilo ;;
            esac
            ;;
        "6")
            echo ""
            echo "If the install finished successfully, you can now type 'reboot'"
            echo "to restart the system."
            echo ""
            exit 0 ;;
        *)
            abort ;;
    esac
}

dodialog 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 VC5 console (ALT-F5).  ALT-F1 will bring you back here." 14 65

dialog --backtitle "$TITLE" --menu "Please select an installation source" 10 35 3 \
"1" "CD-ROM or OTHER SOURCE" \
"2" "FTP/HTTP" 2>$ANSWER || abort

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

if [ "$MODE" = "cd" ]; then
    TITLE="Arch Linux CDROM or OTHER SOURCE Installation"
else
    TITLE="Arch Linux FTP/HTTP Installation"
    dodialog msgbox "If you wish to load your ethernet modules manually, please do so now (consoles 1 thru 4 are active)." 12 65
fi

loop() {
    while $(/bin/true); do
        mainmenu
    done
}

loop

exit 0
