diff --git a/lang/english.trans b/lang/english.trans index d0e7967..11d1ec8 100644 --- a/lang/english.trans +++ b/lang/english.trans @@ -24,16 +24,20 @@ _Not64Bit="\nThis installer only supports x86_64 capable hardware or virtual mac _NoNetwork="\nThis installer needs to be run with an active internet connection in order to update and install packages.\n" # Preparation Menu -_PrepTitle="Prepare System" +_PrepTitle="Prepare System for Install" _PrepBody="\nFollow the below steps in order.\n\nTo begin the install, a root (/) partition must first be mounted and the system settings must be configured (UEFI systems also require a boot partition to be mounted).\n\nIf you have already created a partition table and partition(s) you can begin mounting and skip over the editing step." -_PrepLayout="Keyboard Layout" -_PrepShowDev="Device Tree" -_PrepParts="Edit Partitions" -_PrepLUKS="LUKS (optional)" -_PrepLVM="LVM (optional)" -_PrepMount="Mount Partitions" -_PrepConfig="Configure Install" -_PrepInstall="Install $DIST" +_PrepLayout="Select Keyboard Layout" +_PrepShowDev="Show Device Tree (optional)" +_PrepParts="Edit Partitions (optional)" +_PrepLUKS="LUKS Encryption (optional)" +_PrepLVM="Logical Volume Management (optional)" +_PrepMount="Mount and Format Partitions" +_PrepUser="Create User and Set root Password" +_PrepConfig="Configure System Settings" +_PrepWM="Select Window Manager or Desktop" +_PrepPkg="Select Additional Packages" +_PrepShow="Check Configuration Choices" +_PrepInstall="Begin $DIST Installation" # Configure _ConfHost="System Hostname" @@ -215,5 +219,6 @@ _UserErrTitle="User Name Error" _UserErrBody="\nIncorrect user name.\n\nPlease try again.\n" _UserPassErr="\nThe user passwords entered do not match.\n" _RootPassErr="\nThe root passwords entered do not match.\n" +_UserPassEmpty="\nThe user password cannot be left empty.\n" # vim:tw=9999:syntax=off:nospell diff --git a/src/archlabs-installer b/src/archlabs-installer index 1b5196d..e0834da 100755 --- a/src/archlabs-installer +++ b/src/archlabs-installer @@ -8,170 +8,90 @@ # Some ideas and code has been taken from other installers # AIF, Cnichi, Calamares, The Arch Wiki.. Credit where credit is due -VER="1.8.1" # Installer version -DIST="ArchLabs" # Installer distributor -MNT="/mnt" # Installer mountpoint -ERR="/tmp/errlog" # error log used internally -DBG="/tmp/debuglog" # debug log when passed -d -RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot -LNG="/usr/share/archlabs/installer/lang" # translation file path -BT="$DIST Installer - v$VER" # backtitle used for dialogs -VM="$(dmesg | grep -i "hypervisor")" # is the system a vm +VER="1.8.3" # Installer version +DIST="ArchLabs" # Installer distributor +MNT="/mnt" # Installer mountpoint -ROOT_PART="" # root partition -BOOT_PART="" # boot partition -BOOT_DEVICE="" # device used for BIOS grub install -AUTO_BOOT_PART="" # filled with the boot partition from autopartiton() -BOOTLDR="" # bootloader selected -EXTRA_MNT="" # holder for additional partitions while mounting -EXTRA_MNTS="" # when an extra partition is mounted append it's info -SWAP_PART="" # swap partition or file path -SWAP_SIZE="" # when using a swapfile use this size -NEWUSER="" # username for the primary user -USER_PASS="" # password for the primary user -ROOT_PASS="" # root password -LOGIN_WM="" # default login session -LOGIN_TYPE="" # login manager can be lightdm or xinit -INSTALL_WMS="" # space separated list of chosen wm/de -KERNEL="" # kernel can be linux or linux-lts -WM_PACKAGES="" # full list of packages added during wm/de choice -PACKAGES="" # list of all packages to install including WM_PACKAGES -MYSHELL="" # login shell for root and the primary user -UCODE="" # cpu manufacturer microcode filename (if any) -HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf +main() +{ + if [[ $CURRENT_MENU != "main" && $SAVED ]]; then + CURRENT_MENU="main" + SELECTED=$((SAVED + 1)) + unset SAVED + elif [[ $CURRENT_MENU != "main" ]]; then + SELECTED=1 + CURRENT_MENU="main" + elif (( SELECTED < 11 )); then + ((SELECTED++)) + fi -LUKS="" # empty when not using luks encryption -LUKS_DEV="" # device used for encryption -LUKS_PART="" # partition used for encryption -LUKS_PASS="" # encryption password -LUKS_UUID="" # encrypted partition UUID -LUKS_NAME="" # name used for encryption + tput civis + SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \ + --title " $_PrepTitle " --default-item $SELECTED \ + --cancel-label "Exit" --menu "$_PrepBody" 0 0 0 \ + "1" "$_PrepShowDev" \ + "2" "$_PrepParts" \ + "3" "$_PrepLUKS" \ + "4" "$_PrepLVM" \ + "5" "$_PrepMount" \ + "6" "$_PrepUser" \ + "7" "$_PrepConfig" \ + "8" "$_PrepWM" \ + "9" "$_PrepPkg" \ + "10" "$_PrepShow" \ + "11" "$_PrepInstall") -LVM="" # empty when not using lvm -GROUP_PARTS="" # partitions used for volume group -VOL_GROUP_MB=0 # available space in volume group + if [[ $WARN != true && $SELECTED =~ (2|5) ]]; then + WARN=true + msgbox "$_PrepTitle" "$_WarnMount" + fi -WARN=false # issued mounting/partitioning warning -CONFIG_DONE=false # basic configuration is finished -SEP_BOOT=false # separate boot partition for BIOS -AUTOLOGIN=false # enable autologin for xinit -BROADCOM_WL=false # fixes for broadcom cards eg. BCM4352 - -# amount of RAM in the system in Mb -SYS_MEM="$(awk '/MemTotal/ { - print int($2 / 1024)"M" -}' /proc/meminfo)" - -# parsed string of locales from /etc/locale.gen -LOCALES="$(awk '/\.UTF-8/ { - gsub(/# .*|#/, "") - if ($1) { - print $1 " -" - } -}' /etc/locale.gen)" - -# parsed string of linux console keyboard mappings -CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{ - gsub(/\.map\.gz|.*\//, "") - print $1 " -" -}')" - -# various associative arrays -# { - -# command used to install each bootloader -declare -A BCMDS=( -[syslinux]="syslinux-install_update -iam" -[grub]="grub-install --recheck --force" -[systemd-boot]="bootctl --path=/boot install" -) - -# boot partition mount points for each bootloader -declare -A BMNTS=( -[BIOS-grub]="/boot" -[UEFI-grub]="/boot/efi" -[BIOS-syslinux]="/boot" -[UEFI-systemd-boot]="/boot" -) - -# bootloader options with respective boot partition mountpoint -declare -A BOOTLDRS=( -[BIOS]="grub ${BMNTS[BIOS-grub]} syslinux ${BMNTS[BIOS-syslinux]}" -[UEFI]="systemd-boot ${BMNTS[UEFI-systemd-boot]} grub ${BMNTS[UEFI-grub]}" -) - -# match the wm name with the actual session name used for xinit -declare -A WM_SESSIONS=( -[dwm]='dwm' -[i3-gaps]='i3' -[bspwm]='bspwm' -[xfce4]='startxfce4' -[plasma]='startkde' -[gnome]='gnome-session' -[openbox]='openbox-session' -[cinnamon]='cinnamon-session' -) - -# additional packages installed for each wm/de -declare -A WM_EXT=( -[gnome]="gnome-extra" -[plasma]="kde-applications" -[bspwm]="sxhkd archlabs-skel-bspwm rofi archlabs-polybar" -[xfce4]="xfce4-goodies xfce4-pulseaudio-plugin archlabs-skel-xfce4" -[i3-gaps]="i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar" -[openbox]="obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi" -) - -# files the user can edit during the final stage of install -declare -A EDIT_FILES=( -[2]="/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard /etc/vconsole.conf" -[3]="/etc/locale.conf /etc/default/locale" -[4]="/etc/hostname /etc/hosts" -[5]="/etc/sudoers" -[6]="/etc/mkinitcpio.conf" -[7]="/etc/fstab" -[8]="/etc/crypttab" -[9]="/boot/loader/entries/$DIST.conf" -[10]="/etc/pacman.conf" -[11]="" # login files.. Populated later once login method is chosen -) - -# 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 -declare -A PKG_EXT=( -[vlc]="qt4" -[mpd]="mpc" -[mupdf]="mupdf-tools" -[qt5ct]="qt5-styleplugins" -[vlc]="qt5ct qt5-styleplugins" -[zathura]="zathura-pdf-poppler" -[noto-fonts]="noto-fonts-emoji" -[cairo-dock]="cairo-dock-plug-ins" -[kdenlive]="qt5ct qt5-styleplugins" -[qbittorrent]="qt5ct qt5-styleplugins" -[qutebrowser]="qt5ct qt5-styleplugins" -[kdenlive]="kdebase-runtime dvdauthor frei0r-plugins breeze breeze-gtk" -) - -# mkfs command to format a partition as a given file system -declare -A FS_CMDS=( -[ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q" -[f2fs]="mkfs.f2fs" [jfs]="mkfs.jfs -q" [xfs]="mkfs.xfs -f" [nilfs2]="mkfs.nilfs2 -q" -[ntfs]="mkfs.ntfs -q" [reiserfs]="mkfs.reiserfs -q" [vfat]="mkfs.vfat -F32" -) - -# mount options for a given file system -declare -A FS_OPTS=([vfat]="" [ntfs]="" [ext2]="" [ext3]="" -[ext4]="discard - off dealloc - off nofail - off noacl - off relatime - off noatime - off nobarrier - off nodelalloc - off" -[jfs]="discard - off errors=continue - off errors=panic - off nointegrity - off" -[reiserfs]="acl - off nolog - off notail - off replayonly - off user_xattr - off" -[xfs]="discard - off filestreams - off ikeep - off largeio - off noalign - off nobarrier - off norecovery - off noquota - off wsync - off" -[nilfs2]="discard - off nobarrier - off errors=continue - off errors=panic - off order=relaxed - off order=strict - off norecovery - off" -[f2fs]="data_flush - off disable_roll_forward - off disable_ext_identify - off discard - off fastboot - off flush_merge - off inline_xattr - off inline_data - off inline_dentry - off no_heap - off noacl - off nobarrier - off noextent_cache - off noinline_data - off norecovery - off" -) -# } + case $SELECTED in + 1) + device_tree + ;; + 2) + partition || SELECTED=$((SELECTED - 1)) + ;; + 3) + luks_menu || SELECTED=$((SELECTED - 1)) + ;; + 4) + lvm_menu || SELECTED=$((SELECTED - 1)) + ;; + 5) + mnt_menu || SELECTED=$((SELECTED - 1)) + ;; + 6) + if preinstall_checks; then + user_creation || SELECTED=$((SELECTED - 1)) + fi + ;; + 7) + if preinstall_checks; then + cfg_menu || SELECTED=$((SELECTED - 1)) + fi + ;; + 8) + if preinstall_checks 1; then + select_wm_or_de || SELECTED=$((SELECTED - 1)) + fi + ;; + 9) + if preinstall_checks 1; then + select_packages || SELECTED=$((SELECTED - 1)) + fi + ;; + 10) + preinstall_checks 1 && show_cfg + ;; + 11) + preinstall_checks 1 && install + ;; + *) + yesno "$_CloseInst" "$_CloseInstBody" "Exit" "Back" && die + esac +} ############################################################################### # utility functions @@ -203,18 +123,22 @@ src() ssd() { # returns 0 (true) when the device passed ($1) is NOT a rotational device - local dev=$1 - dev=${dev#/dev/} + local i dev=$1 - if [[ $dev =~ nvme ]]; then - dev=${dev%p[0-9]*} - else - dev=${dev%[0-9]*} + # check for LVM and or LUKS for their origin devices + if [[ $LUKS && ! $LVM && $dev =~ $LUKS_NAME ]]; then + dev="${LUKS_PART}" + elif [[ $LVM && ! $LUKS && ${#GROUP_PARTS[@]} -eq 1 && ${GROUP_PARTS[*]} =~ $dev ]]; then + dev="${GROUP_PARTS[*]}" fi - local i + dev=${dev#/dev/} + [[ $dev =~ nvme ]] && dev=${dev%p[0-9]*} || dev=${dev%[0-9]*} + i=$(cat /sys/block/$dev/queue/rotational 2>/dev/null) - [[ $i && $i -eq 0 ]] || return 1 + + # return value check + (( ${i:-1} == 0 )) } die() @@ -254,23 +178,22 @@ print4() # takes an arbitrary number of input fields and prints them out in fourths on separate lines local str="$*" if [[ ${#str} -gt $(( ${COLUMNS:-$(tput cols)} / 2 )) ]]; then - q=$(awk '{print int(NF / 4)}' <<< "$str") - str="$(awk '{ + str="$(awk -v q="$(awk '{print int(NF / 4)}' <<< "$str")" '{ pkgs1=pkgs2=pkgs3=pkgs4="" - for (i=1;i<'"$q"';i++) { + for (i=1; i/dev/null 2>&1 @@ -345,6 +268,24 @@ load_bcwl() BROADCOM_WL=true } +net_connect() +{ + if ! curl -s --head 'https://www.archlinux.org/mirrorlist/all/' | sed '1q' | grep -qw '200'; then + if [[ $(systemctl is-active NetworkManager) == "active" ]] && hash nmtui >/dev/null 2>&1; then + tput civis + nmtui-connect + if ! curl -s --head 'https://www.archlinux.org/mirrorlist/all/' | sed '1q' | grep -qw '200'; then + return 1 + fi + else + return 1 + fi + fi + + # if we've made it here we likely have a good connection + return 0 +} + system_checks() { if [[ $(whoami) != "root" ]]; then @@ -355,20 +296,12 @@ system_checks() die 1 fi - grep -q 'BCM4352' <<< "$(lspci -vnn -d 14e4:)" && load_bcwl + # setup for specific broadcom chips + grep -q 'BCM4352' <<< "$(lspci -vnn -d 14e4:)" && fix_broadcom_modules - if ! curl -s --head 'https://www.archlinux.org/mirrorlist/all/' | sed '1q' | grep -qw '200'; then - if [[ $(systemctl is-active NetworkManager) == "active" ]] && hash nmtui >/dev/null 2>&1; then - tput civis - nmtui-connect - if ! curl -s --head 'https://www.archlinux.org/mirrorlist/all/' | sed '1q' | grep -qw '200'; then - infobox "$_ErrTitle" "$_NoNetwork" 3 - die 1 - fi - fi - fi + # connect or confirm connection, otherwise bail + net_connect || { infobox "$_ErrTitle" "$_NoNetwork\n$_Exit" 3; die 1; } - return 0 } preinstall_checks() @@ -451,11 +384,7 @@ msgbox() menubox() { - local title="$1" - local body="$2" - local h=$3 - local w=$4 - local n=$5 + local title="$1" body="$2" h=$3 w=$4 n=$5 shift 5 local response if ! response="$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ @@ -590,7 +519,7 @@ select_mailchat() printf "%s" "$pkgs" } -select_professional() +select_prof() { local pkgs="" pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \ @@ -760,9 +689,8 @@ select_device() fi if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then + # auto select without mention (it's annoying) DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")" - msg="\nOnly one device available$([[ $1 == 'boot' ]] && printf " for bootloader"):" - infobox "$_DevSelTitle" "$msg $DEVICE\n" 1 elif (( DEV_COUNT > 1 )); then tput civis if ! DEVICE="$(menubox "$_DevSelTitle " "${msg}$_DevSelBody" 0 0 0 $SYS_DEVS)"; then @@ -809,13 +737,13 @@ check_cryptlvm() # Identify if $part is "crypt" (LUKS on LVM, or LUKS alone) if [[ $(lsblk -lno TYPE "$part") =~ 'crypt' ]]; then - LUKS=' encrypted' + LUKS='encrypted' LUKS_NAME="${part#/dev/mapper/}" for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do if grep -q "$LUKS_NAME" <<< "$(lsblk -lno NAME "$dev")"; then LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME" - LVM=' logical volume' + LVM='logical volume' break fi done @@ -828,7 +756,7 @@ check_cryptlvm() done elif [[ $(lsblk -lno TYPE "$part") =~ 'lvm' ]]; then - LVM=' logical volume' + LVM='logical volume' VOLUME_NAME="${part#/dev/mapper/}" for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do @@ -841,7 +769,7 @@ check_cryptlvm() if grep -q "$LUKS_NAME" <<< "$(lsblk -lno NAME "$dev")"; then LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')" LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME" - LUKS=' encrypted' + LUKS='encrypted' break fi done @@ -1096,7 +1024,7 @@ select_mount_opts() ssd "$part" >/dev/null 2>&1 && opts=$(sed 's/discard - off/discard - on/' <<< "$opts") tput civis - if ! MNT_OPTS="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $title " \ + if ! MNT_OPTS="$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" --title " $title " \ --checklist "$_MntBody" 0 0 0 $opts)" || [[ $MNT_OPTS == "" ]]; then return 1 fi @@ -1253,20 +1181,17 @@ lvm_menu() tput civis local choice - choice="$(menubox "$_PrepLVM" "$_LvmMenu" 0 0 0 \ + choice="$(dialog --cr-wrap --stdout --backtitle "$BT" \ + --title " $_PrepLVM " --menu "$_LvmMenu" 0 0 0 \ "$_LvmCreateVG" "vgcreate -f, lvcreate -L -n" \ "$_LvmDelVG" "vgremove -f" \ "$_LvMDelAll" "lvrmeove, vgremove, pvremove -f" \ "$_Back" "-")" case $choice in - "$_LvmCreateVG") - lvm_create - retval=$? - [[ $retval != 1 ]] && return $retval - ;; - "$_LvmDelVG") lvm_del_vg ;; - "$_LvMDelAll") lvm_del_all ;; + "$_LvmCreateVG") lvm_create && return 0 ;; + "$_LvmDelVG") lvm_del_vg ;; + "$_LvMDelAll") lvm_del_all ;; *) return 0 esac @@ -1434,7 +1359,8 @@ lvm_extra_lvs() lvm_volume_count() { - if ! VOL_COUNT=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_LvmCreateVG " \ + if ! VOL_COUNT=$(dialog --cr-wrap --no-cancel --stdout \ + --backtitle "$BT" --title " $_LvmCreateVG " \ --radiolist "$_LvmLvNumBody1 $VOLUME_GROUP\n$_LvmLvNumBody2" 0 0 0 \ "1" "-" off "2" "-" off "3" "-" off "4" "-" off "5" "-" off \ "6" "-" off "7" "-" off "8" "-" off "9" "-" off); then @@ -1450,28 +1376,29 @@ lvm_partitions() # choose partitions tput civis - if ! GROUP_PARTS="$(dialog --cr-wrap --stdout --backtitle "$BT" \ - --title " $_LvmCreateVG " --checklist "$_LvmPvSelBody" 0 0 0 $PARTS)"; then - return 1 - fi + GROUP_PARTS=($(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ + --title " $_LvmCreateVG " --checklist "$_LvmPvSelBody" 0 0 0 $PARTS)) - return 0 + # return code, when less than 1 part was selected will return non-zero + (( ${#GROUP_PARTS[@]} >= 1 )) } lvm_create_group() { + # get volume group name lvm_group_name || return 1 # loop while setup is not confirmed by the user - while ! yesno "$_LvmCreateVG" "$_LvmPvConfBody1 $VOLUME_GROUP\n\n$_LvmPvConfBody2 $GROUP_PARTS\n"; do + local msg="$_LvmPvConfBody1 $VOLUME_GROUP\n\n$_LvmPvConfBody2" + while ! yesno "$_LvmCreateVG" "$msg ${GROUP_PARTS[*]}\n"; do lvm_partitions || { break; return 1; } lvm_group_name || { break; return 1; } done # create it - vgcreate -f "$VOLUME_GROUP" "$GROUP_PARTS" >/dev/null 2>$ERR - errshow "vgcreate -f $VOLUME_GROUP $GROUP_PARTS" + vgcreate -f "$VOLUME_GROUP" "${GROUP_PARTS[@]}" >/dev/null 2>$ERR + errshow "vgcreate -f $VOLUME_GROUP ${GROUP_PARTS[*]}" GROUP_SIZE=$(vgdisplay "$VOLUME_GROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, "") @@ -1497,7 +1424,7 @@ lvm_create_group() lvm_create() { VOLUME_GROUP="" - GROUP_PARTS="" + GROUP_PARTS=() VOL_GROUP_MB=0 umount_dir $MNT lvm_partitions || return 1 @@ -1507,11 +1434,11 @@ lvm_create() lvm_volume_name "$_LvmLvNameBody1 $_LvmLvNameBody2 (${VOL_GROUP_MB}MB)" || return 1 lvcreate -l +100%FREE "$VOLUME_GROUP" -n "$VOLUME_NAME" >/dev/null 2>$ERR errshow "lvcreate -l +100%FREE $VOLUME_GROUP -n $VOLUME_NAME" - LVM=' logical volume' + LVM='logical volume' tput civis sleep 0.5 local msg="${_Done}$_LvmPvDoneBody1 $VOLUME_GROUP-$VOLUME_NAME (${VOLUME_SIZE:-${VOL_GROUP_MB}MB}) $_LvmPvDoneBody2." - msgbox "$_LvmCreateVG (LV:$VOL_COUNT)" "$msg\n\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $GROUP_PARTS)" + msgbox "$_LvmCreateVG (LV:$VOL_COUNT)" "$msg\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE "${GROUP_PARTS[@]}")" return 0 } @@ -1549,6 +1476,27 @@ lvm_del_all() ############################################################################### # luks functions +luks_menu() +{ + tput civis + local choice + choice="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $_PrepLUKS " \ + --menu "${_LuksMenuBody}${_LuksMenuBody2}${_LuksMenuBody3}" 0 0 0 \ + "$_LuksEncrypt" "cryptsetup -q luksFormat" \ + "$_LuksOpen" "cryptsetup open --type luks" \ + "$_LuksEncryptAdv" "cryptsetup -q -s -c luksFormat" \ + "$_Back" "-")" + + case $choice in + "$_LuksEncrypt") luks_default && return 0 ;; + "$_LuksOpen") luks_open && return 0 ;; + "$_LuksEncryptAdv") luks_keycmd && return 0 ;; + *) return 0 + esac + + luks_menu +} + luks_open() { LUKS_PART="" @@ -1560,9 +1508,11 @@ luks_open() if (( COUNT == 1 )); then LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")" infobox "$_LuksOpen" "${_OnlyOne}: $LUKS_PART\n" 1 - elif ! LUKS_PART="$(menubox "$_LuksOpen" "$_LuksMenuBody" 0 0 0 $PARTS)"; then + elif ! LUKS_PART="$(menubox "$_LuksOpen" "$_LuksMenuBody" 0 0 0 $PARTS)" || ! [[ $LUKS_PART ]]; then return 1 - elif ! luks_pass "$_LuksOpen" "${LUKS_NAME:-cryptroot}"; then + fi + + if ! luks_pass "$_LuksOpen" "${LUKS_NAME:-cryptroot}"; then return 1 fi @@ -1570,7 +1520,7 @@ luks_open() cryptsetup open --type luks $LUKS_PART "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" - LUKS=' encrypted' + LUKS='encrypted' luks_show return 0 } @@ -1586,8 +1536,9 @@ luks_pass() tput cnorm local values if [[ $name == "" ]]; then - if ! values="$(dialog --stdout --separator '~' --ok-label "Submit" \ - --backtitle "$BT" --title " $title " --insecure --mixedform \ + if ! values="$(dialog --stdout --no-cancel --separator '~' \ + --ok-label "Submit" --backtitle "$BT" \ + --title " $title " --insecure --mixedform \ "\nEnter the password to decrypt $ROOT_PART. \nThis is needed to create a keyfile." 14 75 3 \ "$_Password" 1 1 "" 1 $((${#_Password} + 2)) 71 0 1 \ @@ -1597,8 +1548,9 @@ luks_pass() pass="$(awk -F'~' '{print $1}' <<< "$values")" pass2="$(awk -F'~' '{print $2}' <<< "$values")" else - if ! values="$(dialog --stdout --separator '~' --ok-label "Submit" --backtitle "$BT" \ - --title " $title " --insecure --mixedform "$_LuksOpenBody" 16 75 4 \ + if ! values="$(dialog --stdout --no-cancel --separator '~' \ + --ok-label "Submit" --backtitle "$BT" --title " $title " \ + --insecure --mixedform "$_LuksOpenBody" 16 75 4 \ "$_Name" 1 1 "$name" 1 $((${#_Name} + 2)) 71 0 0 \ "$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \ "$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1)"; then @@ -1652,7 +1604,7 @@ luks_default() cryptsetup open $LUKS_PART "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR errshow "cryptsetup open $LUKS_PART $LUKS_NAME" - LUKS=' encrypted' + LUKS='encrypted' luks_show return 0 } @@ -1686,27 +1638,6 @@ luks_show() msgbox "$_LuksEncrypt" "${_LuksEncryptSucc}\n$(lsblk $LUKS_PART -o NAME,MODEL,TYPE,FSTYPE,SIZE)\n" } -luks_menu() -{ - tput civis - local choice - choice="$(menubox "$_PrepLUKS" \ - "${_LuksMenuBody}${_LuksMenuBody2}${_LuksMenuBody3}" 0 0 0 \ - "$_LuksEncrypt" "cryptsetup -q luksFormat" \ - "$_LuksOpen" "cryptsetup open --type luks" \ - "$_LuksEncryptAdv" "cryptsetup -q -s -c luksFormat" \ - "$_Back" "-")" - - case $choice in - "$_LuksEncrypt") luks_default && return 0 ;; - "$_LuksOpen") luks_open && return 0 ;; - "$_LuksEncryptAdv") luks_keycmd && return 0 ;; - *) return 0 - esac - - luks_menu -} - luks_keyfile() { # Only used when choosing grub as bootloader. @@ -1926,11 +1857,11 @@ setup_xinit() case $MYSHELL in "/bin/bash") loginrc=".bash_profile" - rm -rf $MNT/home/$NEWUSER/.{z,mksh}* + rm -rf $MNT/home/$NEWUSER/.{zsh,mksh}* ;; "/usr/bin/mksh") loginrc=".profile" - rm -rf $MNT/home/$NEWUSER/.{z,bash}* + rm -rf $MNT/home/$NEWUSER/.{zsh,bash}* cat >> $MNT/home/$NEWUSER/.mkshrc << EOF # colors in less (manpager) @@ -1959,8 +1890,10 @@ EOF rm -rf $MNT/home/$NEWUSER/.{bash,mksh}* esac - # add the shell login file to the edit list after install - EDIT_FILES[11]+=" /home/$NEWUSER/$loginrc" + if ! [[ ${EDIT_FILES[login]} =~ $loginrc ]]; then + # add the shell login file to the edit list after install + EDIT_FILES[login]+=" /home/$NEWUSER/$loginrc" + fi if [[ $AUTOLOGIN == true ]]; then sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf @@ -2021,8 +1954,14 @@ run_mkinitcpio() fi # new hooks needed in /etc/mkinitcpio.conf if we used LUKS and/or LVM - [[ $LVM ]] && add="lvm2" - [[ $LUKS ]] && add="encrypt$([[ $add ]] && printf " %s" "$add")" + [[ $LUKS ]] && add="encrypt" + + if [[ $LVM && $add ]]; then + add+=" lvm2" + elif [[ $LVM ]]; then + add="lvm2" + fi + sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf chrun "mkinitcpio -p $KERNEL" 2>$ERR @@ -2080,8 +2019,8 @@ package_operations() chrun "pacman -Syyu --noconfirm" chrun "pacman -S iputils --noconfirm" 2>/dev/null chrun "pacman -S base-devel git --needed --noconfirm" 2>/dev/null - chrun "pacman -S $inpkg --needed --noconfirm" - chrun "pacman -Rs $rmpkg --noconfirm" + chrun "for pkg in $(uniq <<< "$inpkg"); do pacman -S $pkg --needed --noconfirm; done" + chrun "for pkg in $(uniq <<< "$rmpkg"); do pacman -Rs $pkg --noconfirm; done" return 0 } @@ -2131,38 +2070,38 @@ setup_boot() setup_grub() { - EDIT_FILES[9]="/etc/default/grub" - + # grub has by far the worst setup of the three however + # the configuration is shorter due to grub-mkconfig + EDIT_FILES[bootloader]="/etc/default/grub" if [[ $SYS == 'BIOS' ]]; then - if [[ $BOOT_DEVICE == "" ]]; then - select_device 'boot' || return 1 - fi - BCMDS[grub]+=" --target=i386-pc $BOOT_DEVICE && grub-mkconfig -o /boot/grub/grub.cfg" + [[ $BOOT_DEVICE ]] || { select_device 'boot' || return 1; } + BCMDS[grub]="${BCMDS[grub]} --bootloader-id=$DIST --target=i386-pc $BOOT_DEVICE" else if [[ $ROOT_PART == */dev/mapper/* && ! $LVM && ! $LUKS_PASS ]]; then luks_pass "$_LuksOpen" "" || return 1 fi - - # the mount mess is needed for os-prober to work properly in the chroot - BCMDS[grub]="mkdir -p /run/udev && mkdir -p /run/lvm && - mount --bind /hostrun/udev /run/udev && - mount --bind /hostrun/lvm /run/lvm && - ${BCMDS[grub]} --efi-directory=${BMNTS[UEFI-grub]} --bootloader-id=$DIST && - grub-mkconfig -o /boot/grub/grub.cfg && - umount /run/udev && umount /run/lvm" + BCMDS[grub]="${BCMDS[grub]} --bootloader-id=$DIST" fi + BCMDS[grub]="mkdir -p /run/udev && + mkdir -p /run/lvm && + mount --bind /hostrun/udev /run/udev && + mount --bind /hostrun/lvm /run/lvm && + ${BCMDS[grub]} && + grub-mkconfig -o /boot/grub/grub.cfg && + umount /run/udev && + umount /run/lvm" return 0 } setup_syslinux() { - EDIT_FILES[9]="/boot/syslinux/syslinux.cfg" + EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg" } setup_systemd-boot() { - EDIT_FILES[9]="/boot/loader/entries/$DIST.conf" + EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf" } prerun_grub() @@ -2181,6 +2120,8 @@ prerun_grub() fi # needed for os-prober module to work properly in the chroot + # once the bootloader install (grub in this case) is done + # these will be umount(ed) and the mount dirs removed mkdir -p /run/lvm mkdir -p /run/udev mkdir -p $MNT/hostrun/lvm @@ -2276,6 +2217,7 @@ install_bootloader() chrun "${BCMDS[$BOOTLDR]}" 2>$ERR echeck "${BCMDS[$BOOTLDR]}" + # remove mounted dirs if any if [[ -d $MNT/hostrun ]]; then umount $MNT/hostrun/udev >/dev/null 2>&1 umount $MNT/hostrun/lvm >/dev/null 2>&1 @@ -2330,9 +2272,9 @@ shim_secure_boot() show_cfg() { - local cmd mnt pkgs - cmd="${BCMDS[$BOOTLDR]}" - mnt="${BMNTS[$SYS-$BOOTLDR]}" + local cmd="${BCMDS[$BOOTLDR]}" + local mnt="${BMNTS[$SYS-$BOOTLDR]}" + local pkgs="${PACKAGES# }" msgbox "$_PrepTitle" " ---------- PARTITION CONFIGURATION ------------ @@ -2379,7 +2321,7 @@ show_cfg() Kernel: ${KERNEL:-None} Sessions: ${INSTALL_WMS:-None} Mirrors: ${MIRROR_CMD:-None} - Packages: $(print4 "${PACKAGES:-None}") + Packages: $(print4 "${pkgs:-None}") " } @@ -2396,13 +2338,6 @@ cfg_menu() fi select_timezone || return 1 - user_creation || return 1 - - tput civis - if ! MYSHELL="$(menubox "$_ShellTitle" "$_ShellBody" 0 0 0 '/usr/bin/zsh' '-' '/bin/bash' '-' '/usr/bin/mksh' '-')"; then - return 1 - fi - if ! KERNEL="$(menubox "$_KernelTitle" "$_KernelBody" 0 0 0 'linux' '-' 'linux-lts' '-')"; then return 1 fi @@ -2454,14 +2389,20 @@ select_language() fi [[ $TERM == 'linux' ]] && setfont $FONT >/dev/null 2>&1 export LANG="$LOC" + return 0 } user_creation() { + tput civis + if ! MYSHELL="$(menubox "$_ShellTitle" "$_ShellBody" 0 0 0 \ + '/usr/bin/zsh' '-' '/bin/bash' '-' '/usr/bin/mksh' '-')"; then + return 1 + fi + tput cnorm local values - if ! values="$(dialog --stdout --no-cancel --separator '~' \ --ok-label "Submit" --backtitle "$BT" --title " $_UserTitle " \ --insecure --mixedform "$_UserBody" 27 75 10 \ @@ -2485,29 +2426,23 @@ user_creation() [[ $rpass == "" && $rpass2 == "" ]] && { rpass="$pass"; rpass2="$pass2"; } # make sure a username was entered and that the passwords match - if [[ ${#user} -eq 0 || $user =~ \ |\' || $user =~ [^a-z0-9] || - $pass == "" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]] - then - if [[ $pass == "" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]]; then - # password was left empty or doesn't match - if [[ $pass == "" ]]; then - msgbox "$_ErrTitle" "\nUser password CANNOT be left empty.\n$_TryAgain" - elif [[ "$rpass" != "$rpass2" ]]; then - msgbox "$_ErrTitle" "$_RootPassErr\n$_TryAgain" - else - msgbox "$_ErrTitle" "$_UserPassErr\n$_TryAgain" - fi - else # bad username - msgbox "$_UserErrTitle" "$_UserErrBody" - user="" - fi - # recursively loop back unless the user cancels - user || return 1 - else - NEWUSER="$user" - USER_PASS="$pass" - ROOT_PASS="$rpass" + if [[ ${#user} -eq 0 || $user =~ \ |\' || $user =~ [^a-z0-9] ]]; then + msgbox "$_UserErrTitle" "$_UserErrBody" + user_creation || return 1 + elif [[ $pass == "" ]]; then + msgbox "$_ErrTitle" "$_UserPassEmpty\n$_TryAgain" + user_creation || return 1 + elif [[ "$rpass" != "$rpass2" ]]; then + msgbox "$_ErrTitle" "$_RootPassErr\n$_TryAgain" + user_creation || return 1 + elif [[ "$pass" != "$pass2" ]]; then + msgbox "$_ErrTitle" "$_UserPassErr\n$_TryAgain" + user_creation || return 1 fi + + NEWUSER="$user" + USER_PASS="$pass" + ROOT_PASS="$rpass" return 0 } @@ -2532,8 +2467,8 @@ select_keymap() 'tr' 'Turkish' 'uz' 'Uzbek' 'ie' 'Irish' 'pk' 'Urdu' 'mv' 'Dhivehi' \ 'np' 'Nepali' 'et' 'Amharic' 'sn' 'Wolof' 'ml' 'Bambara' 'tz' 'Swahili' \ 'ke' 'Swahili' 'bw' 'Tswana' 'ph' 'Filipino' 'my' 'Malay' 'tm' 'Turkmen' \ - 'id' 'Indonesian' 'bt' 'Dzongkha' 'lv' 'Latvian' 'md' 'Moldavian' 'mao' 'Maori' \ - 'by' 'Belarusian' 'az' 'Azerbaijani' 'mk' 'Macedonian' 'kh' 'Khmer' 'epo' 'Esperanto' \ + 'id' 'Indonesian' 'bt' 'Dzongkha' 'lv' 'Latvian' 'md' 'Moldavian' 'mao' 'Maori' \ + 'by' 'Belarusian' 'az' 'Azerbaijani' 'mk' 'Macedonian' 'kh' 'Khmer' 'epo' 'Esperanto' \ 'me' 'Montenegrin')"; then return 1 fi @@ -2561,7 +2496,7 @@ select_timezone() local f="/usr/share/zoneinfo/zone.tab" declare -A SUBZONES for i in America Australia Asia Atlantic Africa Europe Indian Pacific Arctic Antarctica; do - SUBZONES[$i]="$(awk '/'"$i"'\// {gsub(/'"$i"'\//, ""); print $3, $1}' $f)" + SUBZONES[$i]="$(awk '/'"$i"'\// {gsub(/'"$i"'\//, ""); print $3, $1}' $f | sort)" done tput civis @@ -2575,37 +2510,38 @@ select_timezone() return 1 fi - yesno "$_TimeZTitle" "$_TimeZQ $ZONE/$SUBZONE?\n" && return 0 || select_timezone + yesno "$_TimeZTitle" "$_TimeZQ $ZONE/$SUBZONE?\n" || select_timezone } select_wm_or_de() { tput civis - if ! INSTALL_WMS="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \ + if ! INSTALL_WMS="$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ --title " $_WMChoice " --checklist "$_WMChoiceBody\n" 0 0 0 \ "i3-gaps" "A fork of i3 window manager with more features including gaps" off \ "dwm" "A customized fork of dwm, with patches and modifications" off \ "openbox" "A lightweight, powerful, and highly configurable stacking window manager" off \ "bspwm" "A tiling window manager that represents windows as the leaves of a binary tree" off \ "gnome" "A desktop environment that aims to be simple and easy to use" off \ - "cinnamon" "A desktop environment combining a traditional desktop layout with modern graphical effects" off \ - "plasma" "KDE Plasma is a software project currently comprising a full desktop environment" off \ - "xfce4" "A lightweight and modular desktop environment based on GTK+ 2 and 3" off)"; then + "cinnamon" "A desktop environment combining traditional desktop with modern graphical effects" off \ + "plasma" "A kde software project currently comprising a full desktop environment" off \ + "xfce4" "A lightweight and modular desktop environment based on gtk+2/3" off)"; then return 1 fi WM_NUM=$(awk '{print NF}' <<< "$INSTALL_WMS") WM_PACKAGES="${INSTALL_WMS/dwm/}" # remove dwm from package list WM_PACKAGES="${WM_PACKAGES// / }" # remove double spaces + WM_PACKAGES="${WM_PACKAGES# }" # remove leading space # packages needed for the selected WMs/DEs for wm in $INSTALL_WMS; do LOGIN_CHOICES+="$wm - " - if [[ $wm == 'plasma' ]]; then + if [[ ${WM_EXT[$wm]} && $wm == 'plasma' ]]; then if yesno "$_WMChoice" "\nInstall kde-applications?\n\nNOTE: This is a large package group.\n"; then - WM_PACKAGES+=" ${WM_EXT[$wm]}" + WM_PACKAGES+=" ${WM_EXT[plasma]}" fi - else + elif [[ ${WM_EXT[$wm]} ]]; then WM_PACKAGES+=" ${WM_EXT[$wm]}" fi done @@ -2620,39 +2556,33 @@ select_wm_or_de() else if ! LOGIN_WM="$(menubox "$_WMLogin" "$_WMLoginBody" 0 0 0 $LOGIN_CHOICES)"; then return 1 - else - LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}" fi + LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}" fi - - if yesno "$_WMLogin" "$_AutoLoginBody\n"; then - AUTOLOGIN=true - else - AUTOLOGIN=false - fi + yesno "$_WMLogin" "$_AutoLoginBody\n" && AUTOLOGIN=true || AUTOLOGIN=false else AUTOLOGIN=false fi # add packages to the main package list - PACKAGES+=" ${WM_PACKAGES/^ /}" + PACKAGES+=" ${WM_PACKAGES# }" } select_login() { if ! LOGIN_TYPE="$(menubox "$_WMLogin" "$_LoginTypeBody" 0 0 0 \ - "xinit" "Console login without a display manager" \ + "xinit" "Console login without a display manager" \ "lightdm" "Lightweight display manager with a gtk greeter")"; then return 1 fi if [[ $LOGIN_TYPE == 'lightdm' ]]; then WM_PACKAGES+=" lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice" - EDIT_FILES[11]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" + EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" else - WM_PACKAGES="$(sed 's/ lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice//g' <<< "$WM_PACKAGES")" - PACKAGES="$(sed 's/ lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice//g' <<< "$PACKAGES")" - EDIT_FILES[11]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile" + PACKAGES="${PACKAGES// lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice/}" + WM_PACKAGES="${WM_PACKAGES// lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice/}" + EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile" fi } @@ -2667,29 +2597,29 @@ select_packages() fi tput civis - SELECTED=$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \ - --title " $_Packages " --default-item $SELECTED \ - --menu "$_PackageMenu" 0 0 0 \ - "1" "Browsers" \ - "2" "Editors" \ - "3" "Terminals" \ - "4" "Multimedia" \ - "5" "Chat/Mail" \ - "6" "Professional" \ - "7" "System" \ - "8" "Miscellaneous" \ - "9" "$_Done") + SELECTED=$(dialog --cr-wrap --no-cancel --stdout \ + --backtitle "$BT" --title " $_Packages " \ + --default-item $SELECTED --menu "$_PackageMenu" 0 0 0 \ + 1 "Browsers" \ + 2 "Editors" \ + 3 "Terminals" \ + 4 "Multimedia" \ + 5 "Chat/Mail" \ + 6 "Professional" \ + 7 "System" \ + 8 "Miscellaneous" \ + 9 "$_Done") if [[ $SELECTED -lt 9 ]]; then case $SELECTED in - 1) PACKAGES+=" $(select_browsers)" ;; - 2) PACKAGES+=" $(select_editors)" ;; - 3) PACKAGES+=" $(select_terminals)" ;; + 1) PACKAGES+=" $(select_browsers)" ;; + 2) PACKAGES+=" $(select_editors)" ;; + 3) PACKAGES+=" $(select_terminals)" ;; 4) PACKAGES+=" $(select_multimedia)" ;; - 5) PACKAGES+=" $(select_mailchat)" ;; - 6) PACKAGES+=" $(select_professional)" ;; - 7) PACKAGES+=" $(select_managment)" ;; - 8) PACKAGES+=" $(select_extra)" ;; + 5) PACKAGES+=" $(select_mailchat)" ;; + 6) PACKAGES+=" $(select_prof)" ;; + 7) PACKAGES+=" $(select_managment)" ;; + 8) PACKAGES+=" $(select_extra)" ;; esac select_packages fi @@ -2718,7 +2648,9 @@ select_mirrorcmd() MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate --verbose" yesno "$_MirrorTitle" "$_MirrorSetup" "Automatic" "Custom" && return 0 - c="$(json 'country_name' "$(json 'ip' "check&?access_key=${key}&fields=ip")?access_key=${key}&fields=country_name")" + c="$(json 'country_name' \ + "$(json 'ip' \ + "check&?access_key=${key}&fields=ip")?access_key=${key}&fields=country_name")" MIRROR_CMD="reflector --country $c --score 80 --latest 40 --fastest 10 --sort rate --verbose" tput cnorm @@ -2735,7 +2667,9 @@ select_mirrorcmd() 'score': MirrorStatus score; 'delay': MirrorStatus delay.\n" 0 0 "$MIRROR_CMD")" else - c="$(json 'country_code' "$(json 'ip' "check&?access_key=${key}&fields=ip")?access_key=${key}&fields=country_code")" + c="$(json 'country_code' \ + "$(json 'ip' \ + "check&?access_key=${key}&fields=ip")?access_key=${key}&fields=country_code")" local w="https://www.archlinux.org/mirrorlist" if [[ $c ]]; then if [[ $c =~ (CA|US) ]]; then @@ -2744,7 +2678,8 @@ select_mirrorcmd() MIRROR_CMD="curl -s '$w/?country=${c}&protocol=https&use_mirror_status=on'" fi else - MIRROR_CMD="curl -s '$w/?country=US&country=CA&country=NZ&country=GB&country=AU&protocol=https&use_mirror_status=on'" + local countries="country=US&country=CA&country=NZ&country=GB&country=AU" + MIRROR_CMD="curl -s '$w/?$countries&protocol=https&use_mirror_status=on'" fi fi return 0 @@ -2752,46 +2687,36 @@ select_mirrorcmd() edit_configs() { - if [[ $CURRENT_MENU != "edit" ]]; then - SELECTED=1; CURRENT_MENU="edit" - elif (( SELECTED < 11 )); then - (( SELECTED++ )) - fi + [[ $DEBUG == true ]] && str="View log & reboot" || str="Exit & reboot" tput civis - if [[ $DEBUG == true ]]; then - local exitstr="View debug log before the exit & reboot" - else - local exitstr="Exit & reboot" - fi + local choice + choice=$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ + --title " $_EditTitle " --menu "$_EditBody" 0 0 0 "$str" "-" \ + "keyboard" "${EDIT_FILES[keyboard]}" \ + "console" "${EDIT_FILES[console]}" \ + "locale" "${EDIT_FILES[locale]}" \ + "hostname" "${EDIT_FILES[hostname]}" \ + "sudoers" "${EDIT_FILES[sudoers]}" \ + "mkinitcpio" "${EDIT_FILES[mkinitcpio]}" \ + "fstab" "${EDIT_FILES[fstab]}" \ + "crypttab" "${EDIT_FILES[crypttab]}" \ + "bootloader" "${EDIT_FILES[bootloader]}" \ + "pacman" "${EDIT_FILES[pacman]}" \ + "login" "${EDIT_FILES[login]}") - SELECTED=$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ - --title " $_EditTitle " --default-item $SELECTED \ - --menu "$_EditBody" 0 0 0 \ - "1" "$exitstr" \ - "2" "${EDIT_FILES[2]}" \ - "3" "${EDIT_FILES[3]}" \ - "4" "${EDIT_FILES[4]}" \ - "5" "${EDIT_FILES[5]}" \ - "6" "${EDIT_FILES[6]}" \ - "7" "${EDIT_FILES[7]}" \ - "8" "${EDIT_FILES[8]}" \ - "9" "${EDIT_FILES[9]}" \ - "10" "${EDIT_FILES[10]}" \ - "11" "${EDIT_FILES[11]}") - - if [[ ! $SELECTED || $SELECTED -eq 1 ]]; then + if [[ ! $choice || $choice == "$str" ]]; then [[ $DEBUG == true && -r $DBG ]] && vim $DBG # when die() is passed 127 it will call: systemctl -i reboot die 127 else - local existing_files="" - for f in $(printf "%s" "${EDIT_FILES[$SELECTED]}"); do - [[ -e ${MNT}$f ]] && existing_files+=" ${MNT}$f" + local exists="" + for f in $(printf "%s" "${EDIT_FILES[$choice]}"); do + [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f" done - if [[ $existing_files ]]; then - vim -O $existing_files + if [[ $exists ]]; then + vim -O $exists else msgbox "$_ErrTitle" "$_NoFileErr" fi @@ -2803,80 +2728,176 @@ edit_configs() ############################################################################### # entry point -main() -{ - if [[ $CURRENT_MENU != "main" && $SAVED ]]; then - CURRENT_MENU="main" - SELECTED=$((SAVED + 1)) - unset SAVED - elif [[ $CURRENT_MENU != "main" ]]; then - SELECTED=1 - CURRENT_MENU="main" - elif (( SELECTED < 10 )); then - ((SELECTED++)) - fi +# giant ugly variable container :P { - tput civis - SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \ - --title " $_PrepTitle " --default-item $SELECTED \ - --cancel-label "Exit" --menu "$_PrepBody" 0 0 0 \ - "1" "$_PrepShowDev" \ - "2" "$_PrepParts" \ - "3" "$_PrepLUKS" \ - "4" "$_PrepLVM" \ - "5" "$_PrepMount" \ - "6" "$_PrepConfig" \ - "7" "Select WM/DE(s)" \ - "8" "Select Packages" \ - "9" "Check Choices" \ - "10" "$_PrepInstall") +# BULK +# { +ERR="/tmp/errlog" # error log used internally +DBG="/tmp/debuglog" # debug log when passed -d +RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot +LNG="/usr/share/archlabs/installer/lang" # translation file path +BT="$DIST Installer - v$VER" # backtitle used for dialogs +VM="$(dmesg | grep -i "hypervisor")" # is the system a vm - if [[ $WARN != true && $SELECTED =~ (2|5) ]]; then - WARN=true - msgbox "$_PrepTitle" "$_WarnMount" - fi +ROOT_PART="" # root partition +BOOT_PART="" # boot partition +BOOT_DEVICE="" # device used for BIOS grub install +AUTO_BOOT_PART="" # filled with the boot partition from auto_partiton() +BOOTLDR="" # bootloader selected +EXTRA_MNT="" # holder for additional partitions while mounting +EXTRA_MNTS="" # when an extra partition is mounted append it's info +SWAP_PART="" # swap partition or file path +SWAP_SIZE="" # when using a swapfile use this size +NEWUSER="" # username for the primary user +USER_PASS="" # password for the primary user +ROOT_PASS="" # root password +LOGIN_WM="" # default login session +LOGIN_TYPE="" # login manager can be lightdm or xinit +INSTALL_WMS="" # space separated list of chosen wm/de +KERNEL="" # kernel can be linux or linux-lts +WM_PACKAGES="" # full list of packages added during wm/de choice +PACKAGES="" # list of all packages to install including WM_PACKAGES +MYSHELL="" # login shell for root and the primary user +UCODE="" # cpu manufacturer microcode filename (if any) +HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf - case $SELECTED in - 1) - device_tree - ;; - 2) - partition || SELECTED=$((SELECTED - 1)) - ;; - 3) - luks_menu || SELECTED=$((SELECTED - 1)) - ;; - 4) - lvm_menu || SELECTED=$((SELECTED - 1)) - ;; - 5) - mnt_menu || SELECTED=$((SELECTED - 1)) - ;; - 6) - if preinstall_checks; then - cfg_menu || SELECTED=$((SELECTED - 1)) - fi - ;; - 7) - if preinstall_checks 1; then - select_wm_or_de || SELECTED=$((SELECTED - 1)) - fi - ;; - 8) - if preinstall_checks 1; then - select_packages || SELECTED=$((SELECTED - 1)) - fi - ;; - 9) - preinstall_checks 1 && show_cfg - ;; - 10) - preinstall_checks 1 && install - ;; - *) - yesno "$_CloseInst" "$_CloseInstBody" "Exit" "Back" && die - esac -} +LUKS="" # empty when not using luks encryption +LUKS_DEV="" # boot parameter string for LUKS +LUKS_PART="" # partition used for encryption +LUKS_PASS="" # encryption password +LUKS_UUID="" # encrypted partition UUID +LUKS_NAME="" # name used for encryption + +LVM="" # empty when not using lvm +GROUP_PARTS=() # partitions used for volume group +VOL_GROUP_MB=0 # available space in volume group + +WARN=false # issued mounting/partitioning warning +CONFIG_DONE=false # basic configuration is finished +SEP_BOOT=false # separate boot partition for BIOS +AUTOLOGIN=false # enable autologin for xinit +BROADCOM_WL=false # fixes for broadcom cards eg. BCM4352 +# } + +# amount of RAM in the system in Mb +SYS_MEM="$(awk '/MemTotal/ { + print int($2 / 1024)"M" +}' /proc/meminfo)" + +# parsed string of locales from /etc/locale.gen +LOCALES="$(awk '/\.UTF-8/ { + gsub(/# .*|#/, "") + if ($1) { + print $1 " -" + } +}' /etc/locale.gen)" + +# parsed string of linux console keyboard mappings +CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{ + gsub(/\.map\.gz|.*\//, "") + print $1 " -" +}' | sort)" + +# various associative arrays +# { + +# command used to install each bootloader +declare -A BCMDS=( +[syslinux]="syslinux-install_update -iam" +[grub]="grub-install --recheck --force" +[systemd-boot]="bootctl --path=/boot install" +) + +# boot partition mount points for each bootloader +declare -A BMNTS=( +[BIOS-grub]="/boot" +[UEFI-grub]="/boot/efi" +[BIOS-syslinux]="/boot" +[UEFI-systemd-boot]="/boot" +) + +# bootloader options with respective boot partition mountpoint +declare -A BOOTLDRS=( +[BIOS]="grub ${BMNTS[BIOS-grub]} syslinux ${BMNTS[BIOS-syslinux]}" +[UEFI]="systemd-boot ${BMNTS[UEFI-systemd-boot]} grub ${BMNTS[UEFI-grub]}" +) + +# match the wm name with the actual session name used for xinit +declare -A WM_SESSIONS=( +[dwm]='dwm' +[i3-gaps]='i3' +[bspwm]='bspwm' +[xfce4]='startxfce4' +[plasma]='startkde' +[gnome]='gnome-session' +[openbox]='openbox-session' +[cinnamon]='cinnamon-session' +) + +# additional packages installed for each wm/de +declare -A WM_EXT=( +[gnome]="gnome-extra" +[plasma]="kde-applications" +[bspwm]="sxhkd archlabs-skel-bspwm rofi archlabs-polybar" +[xfce4]="xfce4-goodies xfce4-pulseaudio-plugin archlabs-skel-xfce4" +[i3-gaps]="i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar" +[openbox]="obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi" +) + +# files the user can edit during the final stage of install +declare -A EDIT_FILES=( +[keyboard]="/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard" +[console]="/etc/vconsole.conf" +[locale]="/etc/locale.conf /etc/default/locale" +[hostname]="/etc/hostname /etc/hosts" +[sudoers]="/etc/sudoers" +[mkinitcpio]="/etc/mkinitcpio.conf" +[fstab]="/etc/fstab" +[crypttab]="/etc/crypttab" +[bootloader]="/boot/loader/entries/$DIST.conf" +[pacman]="/etc/pacman.conf" +[login]="" # login files.. Populated later once login method is chosen +) + +# 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 +declare -A PKG_EXT=( +[vlc]="qt4" +[mpd]="mpc" +[mupdf]="mupdf-tools" +[qt5ct]="qt5-styleplugins" +[vlc]="qt5ct qt5-styleplugins" +[zathura]="zathura-pdf-poppler" +[noto-fonts]="noto-fonts-emoji" +[cairo-dock]="cairo-dock-plug-ins" +[kdenlive]="qt5ct qt5-styleplugins" +[qbittorrent]="qt5ct qt5-styleplugins" +[qutebrowser]="qt5ct qt5-styleplugins" +[kdenlive]="kdebase-runtime dvdauthor frei0r-plugins breeze breeze-gtk" +) + +# mkfs command to format a partition as a given file system +declare -A FS_CMDS=( +[ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q" +[f2fs]="mkfs.f2fs" [jfs]="mkfs.jfs -q" [xfs]="mkfs.xfs -f" +[nilfs2]="mkfs.nilfs2 -q" [ntfs]="mkfs.ntfs -q" [reiserfs]="mkfs.reiserfs -q" +[vfat]="mkfs.vfat -F32" +) + +# mount options for a given file system +declare -A FS_OPTS=([vfat]="" [ntfs]="" [ext2]="" [ext3]="" +[ext4]="discard - off dealloc - off nofail - off noacl - off relatime - off noatime - off nobarrier - off nodelalloc - off" +[jfs]="discard - off errors=continue - off errors=panic - off nointegrity - off" +[reiserfs]="acl - off nolog - off notail - off replayonly - off user_xattr - off" +[xfs]="discard - off filestreams - off ikeep - off largeio - off noalign - off nobarrier - off norecovery - off noquota - off wsync - off" +[nilfs2]="discard - off nobarrier - off errors=continue - off errors=panic - off order=relaxed - off order=strict - off norecovery - off" +[f2fs]="data_flush - off disable_roll_forward - off disable_ext_identify - off discard - off fastboot - off flush_merge - off inline_xattr - off inline_data - off inline_dentry - off no_heap - off noacl - off nobarrier - off noextent_cache - off noinline_data - off norecovery - off" +) +# } + +# } # trap Ctrl-C to properly exit trap sigint INT