OSDN Git Service

Fix: issue when entering mount menu
[pacbang-linux/installer-arch.git] / archlabs-installer
index e7b39c3..bdc2e30 100755 (executable)
@@ -5,24 +5,23 @@
 # Some ideas and code reworked from other resources
 # AIF, Cnichi, Calamares, Arch Wiki.. Credit where credit is due
 
-VER="2.0.47"     # installer version
+VER="2.0.50"     # installer version
 DIST="ArchLabs"  # linux distributor
 MNT="/mnt"       # install mountpoint
 ANS="/tmp/ans"   # dialog answer file
 
-
 # ------------------------------------------------------ #
-# if you manually mount your partitions then you
-# need to set these values to avoid using the mount menu.
+# When manually mounting your partitions, you need
+# to set these values to avoid using the mount menu.
 # ------------------------------------------------------ #
 
-# root partition, eg/ /dev/sda2
+# root partition, eg. /dev/sda2
 ROOT_PART=''
 
 # boot partition, required on UEFI eg. /dev/sda1
 BOOT_PART=''
 
-# device used for some bootloader install process, eg. /dev/sda
+# boot device, used for some bootloaders eg. /dev/sda
 BOOT_DEV=''
 
 # bootloader to use, can be:
@@ -38,23 +37,30 @@ BOOTDIR='boot'
 
 # bulk default values {
 
+# these values will be selected during the install, it is not recommended
+# to edit them here unless you know what you're doing.
+
+UCODE=''          # cpu microcode (if any), can be: amd-ucode, intel-ucode
+KERNEL=''         # linux kernel, can be: linux, linux-lts, linux-zen, or linux-hardened
+MYSHELL=''        # full path for the shell, eg. /usr/bin/zsh
+
+SWAP_PART=''      # swap partition or file path
+SWAP_SIZE=''      # swap size, only used when creating a swapfile
+
 EXMNT=''          # holder for additional partitions while mounting
 EXMNTS=''         # when an extra partition is mounted append it's info
 
 FONT="ter-i16n"   # font used for the linux console
 HOOKS="shutdown"  # list of additional HOOKS to add in /etc/mkinitcpio.conf
 
-LOGINRC=''        # login shell rc file, eg. .zprofile, .bash_profile, .profile
-LOGIN_WM=''       # default login session to be placed in ~/.xinitrc
 LOGIN_TYPE=''     # login manager can be: lightdm, xinit
-INSTALL_WMS=''    # space separated list of chosen wm/de
+LOGIN_WM=''       # default login session to be placed in ~/.xinitrc
+LOGINRC=''        # login shell rc file, eg. .zprofile, .bash_profile, .profile
 
-UCODE=''          # cpu microcode (if any), eg. amd-ucode, intel-ucode
-KERNEL=''         # can be linux, linux-lts, linux-zen, or linux-hardened
-MYSHELL=''        # full path for the shell, eg. /usr/bin/zsh
+INSTALL_WMS=''    # space separated list of chosen wm/de
 
-WM_PKGS=''        # full list of packages added during wm/de choice
-PACKAGES=''       # list of all packages to install including WM_PKGS
+WM_PKGS=''        # full list of packages added during wm/de choice (not user edited)
+PACKAGES=''       # list of all packages to install including WM_PKGS (not user edited)
 USER_PKGS=''      # packages selected by the user during install
 
 NEWUSER=''        # username for the new user
@@ -82,9 +88,6 @@ FORMATTED=''      # partitions we formatted and should allow skipping
 AUTO_ROOT_PART='' # root value from auto partition
 AUTO_BOOT_PART='' # boot value from auto partition
 
-SWAP_PART=''      # swap partition or file path
-SWAP_SIZE=''      # swap size, only used when creating a swapfile
-
 # iso base, pacstrap when running the installer from a stock arch iso
 ISO_BASE="b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool wpa_supplicant "
 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
@@ -136,11 +139,11 @@ SHL=$((LINES - 20))
 
 # commands used to install each bootloader (most get modified during runtime) {
 declare -A BCMDS=(
-[refind-efi]='refind-install'
-[grub]='grub-install --recheck --force'
-[syslinux]='syslinux-install_update -i -a -m'
-[efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
-[systemd-boot]='bootctl --path=/boot install'
+[refind-efi]='refind-install'                    # minor modification
+[grub]='grub-install --recheck --force'          # heavily modified
+[syslinux]='syslinux-install_update -i -a -m'    # modified on UEFI
+[efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' # heavily modified
+[systemd-boot]='bootctl --path=/boot install'    # not modified
 ) # }
 
 # executable name for each wm/de {
@@ -157,22 +160,22 @@ declare -A WM_SESSIONS=(
 [cinnamon]='cinnamon-session'
 ) # }
 
-# packages installed for each wm/de {
+# packages installed for each wm/de, most are depends of the skel packages {
 declare -A WM_EXT=(
-[dwm]=''
-[gnome]=''
-[awesome]='awesome'
-[plasma]='kdebase-meta'
-[bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
-[fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
-[i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
-[openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
-[xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
+[dwm]=''                # NA
+[gnome]=''              # NA
+[awesome]=''            # NA
+[plasma]='kdebase-meta' # base plasma application set
+[bspwm]=''              # see deps of bspwm-skel
+[fluxbox]=''            # see deps of fluxbox-skel
+[i3-gaps]=''            # see deps of i3-gaps-skel
+[openbox]=''            # see deps of openbox-skel
+[xfce4]='xfce4-goodies' # see deps of xfce4-skel
 ) # }
 
 # files that can be edited after install is complete {
 declare -A EDIT_FILES=(
-[login]=''
+[login]='' # login is populated once we know the username and shell
 [fstab]='/etc/fstab'
 [sudoers]='/etc/sudoers'
 [crypttab]='/etc/crypttab'
@@ -185,7 +188,7 @@ declare -A EDIT_FILES=(
 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
 ) # }
 
-# mkfs command for formatting each offered filesystem {
+# mkfs command for filesystem formatting {
 declare -A FS_CMDS=(
 [f2fs]='mkfs.f2fs'
 [jfs]='mkfs.jfs -q'
@@ -199,12 +202,12 @@ declare -A FS_CMDS=(
 [reiserfs]='mkfs.reiserfs -q'
 ) # }
 
-# mount options for each offered filesystem (if any {
+# mount options for each filesystem (if any) {
 declare -A FS_OPTS=(
-[vfat]=''
-[ntfs]=''
-[ext2]=''
-[ext3]=''
+[vfat]=''  # NA
+[ntfs]=''  # NA
+[ext2]=''  # NA
+[ext3]=''  # NA
 [jfs]='discard errors=continue errors=panic nointegrity'
 [reiserfs]='acl nolog notail replayonly user_xattr off'
 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
@@ -216,7 +219,7 @@ declare -A FS_OPTS=(
 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
 #          and it uses/requires some additional packages,
 #          you can add them here to keep it simple: [package]="extra"
-#          duplicates are removed with `uniq` before install
+#          duplicates are not added
 declare -A PKG_EXT=(
 [vlc]='qt4'
 [mpd]='mpc'
@@ -416,9 +419,9 @@ select_login()
        fi
 
        if [[ $LOGIN_TYPE == 'lightdm' ]]; then
+               AUTOLOGIN=''
                LOGIN_PKGS="lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
                EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
-               AUTOLOGIN=''
        else
                if (( WM_NUM == 1 )); then
                        LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
@@ -427,7 +430,10 @@ select_login()
                        LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
                fi
 
-               local txt="\nDo you want autologin enabled for $NEWUSER?\n\nIf so the following two files will be created (disable autologin by removing them):\n\n  - /home/$NEWUSER/$LOGINRC (this runs startx when logging in on tty1)\n  - /etc/systemd/system/getty@tty1.service.d/autologin.conf (this logs in $NEWUSER without a password)\n"
+               local txt="\nDo you want autologin enabled for $NEWUSER?\n\n"
+               txt+="If so the following two files will be created (disable autologin by removing them):\n\n"
+               txt+="- /home/$NEWUSER/$LOGINRC (run startx when logging in on tty1)\n"
+               txt+="- /etc/systemd/system/getty@tty1.service.d/autologin.conf (login $NEWUSER without password)\n"
                yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
                LOGIN_PKGS="xorg-xinit"
                EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
@@ -710,14 +716,14 @@ select_packages()
 
 part_menu()
 {
-       check_background_install || return 0
+       is_bg_install || return 0
        local device choice devhash
        devhash="$(lsblk -f | base64)"
        umount_dir $MNT
        part_device || return 1
        device="$DEVICE"
 
-       while true; do
+       while :; do
                choice=""
                if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
                        dlg choice menu "Edit Partitions" "$_part" \
@@ -931,7 +937,7 @@ part_shrink()
                                mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
                                min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
                                max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
-                               umount $MNT >/dev/null 2>&1
+                               umount_dir $MNT
                                tput cnorm
                                if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
                                        size=$(< "$ANS")
@@ -1083,7 +1089,7 @@ part_mountconf()
 
 select_menu()
 {
-       check_background_install || return 0
+       is_bg_install || return 0
        lvm_detect
        umount_dir $MNT
        part_find 'part|lvm|crypt' || { SEL=2; return 1; }
@@ -1193,13 +1199,22 @@ select_filesystem()
 
 select_efi_partition()
 {
-       if (( COUNT == 1 )); then
-               BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
-       elif [[ $AUTO_BOOT_PART ]]; then
-               BOOT_PART="$AUTO_BOOT_PART"
-               return 0 # were done here
+       local pts size dev isize bsize ptcount=0
+
+       # walk partition list and skip ones that are too small/big for boot
+       while read -r dev size; do
+               size_t="${size: -1:1}"  # size type eg. K, M, G, T
+               isize=${size:0:-1}      # remove trailing size type character
+               isize=${isize%.*}       # remove any decimal (round down)
+               [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
+       done <<< "$PARTS"
+
+       if [[ $AUTO_BOOT_PART ]]; then
+               BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
+       elif (( ptcount == 1 )); then
+               BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
        else
-               dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
+               dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
        fi
 
        [[ $BOOT_PART ]] || return 1
@@ -1218,13 +1233,23 @@ select_efi_partition()
 
 select_boot_partition()
 {
+       local pts size dev isize bsize ptcount=0
+
+       # walk partition list and skip ones that are too small/big for boot
+       while read -r dev size; do
+               size_t="${size: -1:1}"  # size type eg. K, M, G, T
+               isize=${size:0:-1}      # remove trailing size type character
+               isize=${isize%.*}       # remove any decimal (round down)
+               [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
+       done <<< "$PARTS"
+
        if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
                BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
        elif [[ $LUKS && ! $LVM ]]; then
-               dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
+               dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
                [[ $BOOT_PART ]] || return 1
        else
-               dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
+               dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
                [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
        fi
 
@@ -1241,12 +1266,24 @@ select_boot_partition()
 
 select_root_partition()
 {
+       local pts size dev isize bsize ptcount=0
+
+       # walk partition list and skip ones that are too small for / (root)
+       while read -r dev size; do
+               size_t="${size: -1:1}"  # size type eg. K, M, G, T
+               isize=${size:0:-1}      # remove trailing size type character
+               isize=${isize%.*}       # remove any decimal (round down)
+               [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
+       done <<< "$PARTS"
+
        if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
                ROOT_PART="$AUTO_ROOT_PART"
-       elif (( COUNT == 1 )); then
-               ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
+               part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
+               return 0  # we're done here
+       elif (( ptcount == 1 )); then  # only one available device
+               ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$pts")"
        else
-               dlg ROOT_PART menu "Mount Root" "\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 8G will not be shown here." $PARTS
+               dlg ROOT_PART menu "Mount Root" "\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 8G will not be shown here." $pts
        fi
        [[ $ROOT_PART ]] || return 1
 
@@ -1258,10 +1295,16 @@ select_root_partition()
 
 select_extra_partitions()
 {
-       local part
-       while (( COUNT > 0 )); do
+       local part pts size dev isize bsize ptcount=0
+
+       # walk partition list and skip ones that are too small to be usable
+       while read -r dev size; do
+               [[ ${size: -1:1} =~ [KM] ]] || { pts+="$dev $size "; (( ptcount++ )); }
+       done <<< "$PARTS"
+
+       while (( ptcount > 0 )); do
                part=''
-               dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
+               dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $pts || break
                if [[ $part == 'done' ]]; then
                        break
                elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
@@ -1294,7 +1337,7 @@ install_main()
        chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
        sleep 1
 
-       while true; do
+       while :; do
                dlg choice menu "Finalization" "$_edit" \
                        finished   "exit the installer and reboot" \
                        keyboard   "${EDIT_FILES[keyboard]}" \
@@ -1338,7 +1381,7 @@ install_base()
                done
                trap - EXIT
                unset RSYNC_PID MIRROR_PID
-       elif [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
+       elif hash rsync >/dev/null 2>&1 && [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
                rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
                errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
                install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
@@ -1425,8 +1468,10 @@ install_boot()
        fi
 
        if [[ $SYS == 'UEFI' ]]; then
+               # our old installs
                find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
-               find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'boot' -type d -delete
+               # generic BOOT/ dir
+               find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
        fi
 
        prerun_$BOOTLDR
@@ -1434,8 +1479,8 @@ install_boot()
        errshow 1 "${BCMDS[$BOOTLDR]}"
 
        if [[ -d $MNT/hostrun ]]; then
-               umount $MNT/hostrun/udev >/dev/null 2>&1
-               umount $MNT/hostrun/lvm >/dev/null 2>&1
+               # cleanup the bind mounts we made earlier for the grub-probe module
+               umount_dir $MNT/hostrun/{udev,lvm}
                rm -rf $MNT/hostrun >/dev/null 2>&1
        fi
 
@@ -1460,10 +1505,11 @@ install_user()
 {
        chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
        errshow 1 "set root password"
-       if [[ $MYSHELL != *zsh ]]; then
+       if [[ $MYSHELL != "/usr/bin/zsh" ]]; then
+               # root uses zsh by default, change it if something else was chosen
                chrun "usermod -s $MYSHELL root" 2>$ERR
                errshow 1 "usermod -s $MYSHELL root"
-               [[ $MYSHELL == "/usr/bin/mksh" ]] && cp -fv $MNT/etc/skel/.mkshrc /root/.mkshrc
+               [[ $MYSHELL == '/usr/bin/mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
        fi
 
        local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
@@ -1483,9 +1529,10 @@ install_user()
 
        [[ $INSTALL_WMS == *dwm* ]] && install_suckless
        [[ $INSTALL_WMS == *awesome* ]] && install_awesome
-       
+       [[ $WM_PKGS == *xfce* ]] && echo 'volumeicon &' >> $MNT/home/$NEWUSER/.xprofile
+
        # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
-       if [[ $LOGIN_WM =~ (startkde|gnome-session) ]]; then
+       if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE == 'lightdm' && $WM_PKGS =~ (plasma|gnome)) ]]; then
                sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
                sed -i '/nitrogen/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
                sed -i '/al-compositor/d' $MNT/home/$NEWUSER/.xprofile $MNT/root/.xprofile
@@ -1512,11 +1559,12 @@ install_xinit()
 # sourced by ${MYSHELL##*/} when used as a login shell
 
 # automatically run startx when logging in on tty1
-[[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && exec startx -- vt1
+if [ -z \$DISPLAY ] && [ \$XDG_VTNR -eq 1 ]; then
+    exec startx
+fi
 EOF
        else
                rm -rf $SERVICE
-               rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile}
        fi
 }
 
@@ -1548,6 +1596,8 @@ EOF
 
 install_awesome()
 {
+       # downloads and sets up @elenapan's awesome WM config hosted on github
+
        if chrun "git clone https://github.com/elenapan/archlabs-awesome /home/$NEWUSER/archlabs-awesome"; then
                cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" "/mnt/home/$NEWUSER"
                cp -rT "/mnt/home/$NEWUSER/archlabs-awesome" /mnt/etc/skel
@@ -1564,26 +1614,46 @@ install_packages()
        local rmpkg=""
        local inpkg="$PACKAGES $USER_PKGS"
 
+       [[ -x $MNT/usr/bin/X ]] || inpkg+=" $BASE_PKGS"
+
        if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
                rmpkg+=" archlabs-installer"
        elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
                rm -f "$MNT/usr/bin/archlabs-installer"
        fi
 
+       # add extras or missed packages gathered throughout the install
        [[ $UCODE ]] && inpkg+=" $UCODE"
-       [[ $MYSHELL == *mksh ]] && inpkg+=" mksh"
        [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
-       [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
-       [[ $MYSHELL == '/usr/bin/zsh' ]] && inpkg+=" zsh-completions"
+       [[ $MYSHELL == "/usr/bin/mksh" ]] && inpkg+=" mksh"
+       if [[ $MYSHELL == '/usr/bin/zsh' ]]; then
+               inpkg+=" zsh-completions"
+       else
+               rmpkg+=" zsh"
+       fi
+
+       # packages only installed for certain WM/DE
        [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
        [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
 
+       # ensure a terminal gets installed
+       [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
+
+       # update fully first to avoid issues
        chrun "pacman -Syyu --noconfirm"
+
+       # remove packages we no longer want
        [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
+
+       # for some reason the user has "no network" after install even though the
+       # system is connected, reinstalling iputils fixes it
        chrun "pacman -S iputils --noconfirm"
+
+       # install all the packages chosen throughout the install
        chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
        errshow 1 "pacman -S $inpkg --needed --noconfirm"
 
+       # extras for bootloaders
        if [[ $BOOTLDR == 'grub' ]]; then
                if [[ $SYS == 'BIOS' ]]; then
                        chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
@@ -1599,13 +1669,16 @@ install_packages()
                chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
                errshow 1 "pacman -S efibootmgr --needed --noconfirm"
        fi
+
        sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
+
        return 0
 }
 
 install_suckless()
 {
        mkdir -pv $MNT/home/$NEWUSER/suckless
+
        for i in dwm dmenu st; do
                if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
                        chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
@@ -1638,17 +1711,15 @@ install_mkinitcpio()
 
 install_mirrorlist()
 {
-       mfile="$1"
+       local mfile="$1"  # output mirrorlist file
 
        if hash reflector >/dev/null 2>&1; then
                reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
        elif hash rankmirrors >/dev/null 2>&1; then
                ip_add="$(curl -fsSL "http://api.ipstack.com/check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip" |
                        python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
-
                country="$(curl -fsSL "http://api.ipstack.com/${ip_add}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code" |
                        python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")"
-
                if [[ "$country" ]]; then
                        if [[ $country =~ (CA|US) ]]; then
                                mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
@@ -1661,7 +1732,7 @@ install_mirrorlist()
                        mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
                fi
 
-               curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >/etc/pacman.d/mirrorlist
+               curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$mfile"
        fi
 
        return 0
@@ -1670,12 +1741,13 @@ install_mirrorlist()
 install_background()
 {
        if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
-               yesno "Background Install" "\nSome parts of the install can be done in the background now, base unpack, mirrorlist sort, system update, and base packages.\n\nDo you want to start the background process?\n" || return 0
+               yesno "Background Install" "\nBegin install in the background?\n" || return 0
                rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
                RSYNC_PID=$!
-               ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
+               ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && sleep 1 && mkdir -p $MNT/var/lib/pacman && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" >> /tmp/bg_out 2>&1 ) &
                MIRROR_PID=$!
-               trap "kill $RSYNC_PID 2>/dev/null; kill $MIRROR_PID 2>/dev/null" EXIT
+               # end the background processes before exiting
+               trap "kill $RSYNC_PID $MIRROR_PID 2>/dev/null" EXIT
        fi
        return 0
 }
@@ -1691,9 +1763,9 @@ setup_grub()
                [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
                BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
        else
-               if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
-                       luks_pass "$_luksopen" 1 || return 1
-               fi
+               if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
+               #       luks_pass "$_luksopen" 1 || return 1
+               fi
                BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
                grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
                grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
@@ -1727,8 +1799,7 @@ prerun_grub()
        fi
 
        # setup for os-prober module
-       mkdir -p /run/{lvm,udev}
-       mkdir -p $MNT/hostrun/{lvm,udev}
+       mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
        mount --bind /run/lvm $MNT/hostrun/lvm
        mount --bind /run/udev $MNT/hostrun/udev
 
@@ -1745,7 +1816,6 @@ prerun_efistub()
        BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
                efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
                -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
-       return 0
 }
 
 setup_syslinux()
@@ -1756,7 +1826,6 @@ setup_syslinux()
                EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
                BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
                efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
-
        fi
 }
 
@@ -1898,7 +1967,7 @@ EOF
 
 lvm_menu()
 {
-       check_background_install || return 1
+       is_bg_install || return 1
        lvm_detect
        local choice
        dlg choice menu "Logical Volume Management" "$_lvmmenu" \
@@ -1954,7 +2023,7 @@ get_lv_size()
 {
        local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
 
-       while true; do
+       while :; do
                ERR_SIZE=0
                dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
                if [[ -z $VOLUME_SIZE ]]; then
@@ -2109,7 +2178,7 @@ lvm_volume_name()
 luks_menu()
 {
        local choice
-       check_background_install || return 1
+       is_bg_install || return 1
        dlg choice menu "LUKS Encryption" "$_luksmenu" \
                "$_luksnew"  "cryptsetup -q luksFormat" \
                "$_luksopen" "cryptsetup open --type luks" \
@@ -2278,28 +2347,20 @@ ofn()
 
 die()
 {
-       local exitcode="$1"
+       local ecode="$1"
+
        trap - INT
-       trap - TSTP
        tput cnorm
        if [[ -d $MNT ]] && command cd /; then
                umount_dir $MNT
-               if (( exitcode == 127 )); then
-                       umount -l /run/archiso/bootmnt
+               if (( ecode == 127 )); then
+                       umount_dir /run/archiso/bootmnt
                        sleep 0.5
-                       systemctl -i reboot
+                       reboot -f
                fi
        fi
-
-       # restore custom linux console 0-15 colors when not rebooting
-       if [[ $TERM == 'linux' ]]; then
-               colors=("\e]P0191919" "\e]P1D15355" "\e]P2609960" "\e]P3FFCC66"
-               "\e]P4255A9B" "\e]P5AF86C8" "\e]P62EC8D3" "\e]P7949494" "\e]P8191919" "\e]P9D15355"
-               "\e]PA609960" "\e]PBFF9157" "\e]PC4E88CF" "\e]PDAF86C8" "\e]PE2ec8d3" "\e]PFE1E1E1")
-               printf "%b" "${colors[@]}" && clear && unset col
-       fi
-
-       exit "$exitcode"
+       termcol
+       exit "$ecode"
 }
 
 dlg()
@@ -2310,12 +2371,8 @@ dlg()
        
        tput civis
        case "$dialog_type" in
-               menu)
-                       dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1
-                       ;;
-               check)
-                       dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1
-                       ;;
+               menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
+               check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
                input)
                        tput cnorm
                        local def="$1"
@@ -2344,8 +2401,8 @@ msg()
 yesno()
 {
        local title="$1" body="$2" yes='Yes' no='No'
-       (( $# >= 3 )) && local yes="$3"
-       (( $# >= 4 )) && local no="$4"
+       (( $# >= 3 )) && yes="$3"
+       (( $# >= 4 )) && no="$4"
        tput civis
        if (( $# == 5 )); then
                dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
@@ -2377,6 +2434,7 @@ sigint()
 print4()
 {
        local str="$*"
+
        if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
                str="$(awk '{
                        i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
@@ -2392,14 +2450,39 @@ print4()
        fi
 }
 
+termcol()
+{
+       local colors=(
+       "\e]P0191919" # #191919
+       "\e]P1D15355" # #D15355
+       "\e]P2609960" # #609960
+       "\e]P3FFCC66" # #FFCC66
+       "\e]P4255A9B" # #255A9B
+       "\e]P5AF86C8" # #AF86C8
+       "\e]P62EC8D3" # #2EC8D3
+       "\e]P7949494" # #949494
+       "\e]P8191919" # #191919
+       "\e]P9D15355" # #D15355
+       "\e]PA609960" # #609960
+       "\e]PBFF9157" # #FF9157
+       "\e]PC4E88CF" # #4E88CF
+       "\e]PDAF86C8" # #AF86C8
+       "\e]PE2ec8d3" # #2ec8d3
+       "\e]PFE1E1E1" # #E1E1E1
+       )
+
+       [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
+}
+
 errshow()
 {
-       exit_code="$?"
-       (( exit_code == 0 )) && return 0
+       [ $? -eq 0 ] && return 0
 
        local fatal=0 err=""
        err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
+
        (( $1 == 1 )) && { fatal=1; shift; }
+
        local txt="\nThe command exited abnormally:\n\n$1\n\n"
 
        if [[ $err ]]; then
@@ -2408,15 +2491,14 @@ errshow()
                txt+="With no error message:\n\n"
        fi
 
-       if (( fatal == 1 )); then
+       if (( fatal )); then
                txt+="Errors at this stage are fatal and the install cannot continue.\n"
        else
                txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
        fi
-
        msg "Install Error" "$txt"
 
-       if (( fatal == 1 )); then
+       if (( fatal )); then
                [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
                die 1
        fi
@@ -2433,31 +2515,31 @@ load_bcm()
 
 prechecks()
 {
-       if [[ $1 -ge 0 ]] && ! grep -qw "$MNT" /proc/mounts; then
+       local i=1
+
+       if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
                msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
-               SEL=4
-               return 1
+               SEL=4 i=0
        elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
                msg "No Bootloader" "\nBootloader must be selected first.\n" 2
-               SEL=5
-               return 1
+               SEL=5 i=0
        elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
                msg "No User" "\nA user must be created first.\n" 2
-               SEL=6
-               return 1
+               SEL=6 i=0
        elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
                msg "Not Configured" "\nSystem configuration must be done first.\n" 2
-               SEL=7
-               return 1
+               SEL=7 i=0
        fi
-       return 0
+       (( i )) # return code
 }
 
 umount_dir()
 {
-       swapoff -a
-       [[ -d $1 ]] && umount -R "$1" >/dev/null 2>&1
-       return 0
+       mount | grep -q 'swap' && swapoff -a
+       for dir; do
+               [[ -d $dir && "$(mount | grep "on $dir ")" ]] || continue
+               umount "$dir" 2>/dev/null || { sleep 0.5; umount -f "$dir" 2>/dev/null || umount -l "$dir"; }
+       done
 }
 
 chk_connect()
@@ -2473,9 +2555,13 @@ net_connect()
        else
                if hash nmtui >/dev/null 2>&1; then
                        tput civis
-                       [[ $TERM == 'linux' ]] && printf "%b" "\e]P1191919" "\e]P4191919"
-                       nmtui-connect
-                       [[ $TERM == 'linux' ]] && printf "%b" "\e]P1D15355" "\e]P4255a9b"
+                       if [[ $TERM == 'linux' ]]; then
+                               printf "%b" "\e]P1191919" "\e]P4191919"
+                               nmtui-connect
+                               printf "%b" "\e]P1D15355" "\e]P4255a9b"
+                       else
+                               nmtui-connect
+                       fi
                        chk_connect
                else
                        return 1
@@ -2483,6 +2569,13 @@ net_connect()
        fi
 }
 
+is_bg_install()
+{
+       [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
+       msg "Install Running" "\nA background install process is currently running.\n" 2
+       return 1
+}
+
 system_devices()
 {
        IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
@@ -2529,16 +2622,12 @@ system_identify()
        _prep+="\n  - Basic system configuration, kernel, shell, login, packages, etc..\n\nOnce you're happy with the choices and the required steps are complete, the main install can be started."
 }
 
-check_background_install()
-{
-       [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
-       msg "Install Running" "\nA background install process is currently running.\n" 2
-       return 1
-}
-
 ###############################################################################
 # entry point
 
+# enable some nicer colours in the linux console
+termcol
+
 if (( UID != 0 )); then
        msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
        die 1
@@ -2559,16 +2648,12 @@ msg "Welcome to the $DIST Installer" "\nThis will help you get $DIST setup on yo
 
 select_keymap || { clear; die 0; }
 
-if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
-       load_bcm
-fi
+# try to fix problematic broadcom wireless chipset before network check
+lspci -vnn -d 14e4: | grep -q 'BCM4352' && load_bcm
 
-if ! net_connect; then
-       msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
-       die 1
-fi
+net_connect || { msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2; die 1; }
 
-while true; do
+while :; do
        select_main
 done