diff --git a/archlabs-installer b/archlabs-installer index ce53952..e4212c5 100755 --- a/archlabs-installer +++ b/archlabs-installer @@ -8,7 +8,7 @@ # check for syntax errors # set -n -VER=2.1.5 +VER=2.1.6 # default values { @@ -19,12 +19,12 @@ FONT=ter-i16n # font used for the linux console HOOKS=shutdown # additional mkinitcpio HOOKS SEL=0 # currently selected menu item SYS=Unknown # bios type, to be determined: UEFI/BIOS +BG=/tmp/bgout # output from background process ERR=/tmp/errlog # stderr log used internally by errshow() DBG=/tmp/debuglog # debug log file when passed -d RUN=/run/archiso/bootmnt/arch/boot # path for live system /boot VM="$(dmesg | grep -i hypervisor)" # system running in a virtual machine EXMNTS="" # extra partitions that were mounted, used to verify mountpoint and show user -FORMATTED="" # partitions that have been formatted, allows skipping the format step USER_CMD="" # optional command(s) entered by the user to run in the chroot export DIALOGOPTS="--cr-wrap" # dialog environment variable to hold default options, see `man dialog` @@ -36,7 +36,7 @@ AL_BASE_PKGS="archlabs-keyring archlabs-icons archlabs-fonts archlabs-themes " AL_BASE_PKGS+="archlabs-baph archlabs-wallpapers archlabs-scripts archlabs-skel-base" WM_BASE_PKGS="arandr nitrogen polkit-gnome network-manager-applet " -WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool compton wmctrl feh " +WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool picom wmctrl feh " WM_BASE_PKGS+="gnome-keyring dunst gsimplecal xfce4-power-manager xfce4-settings" SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)" @@ -55,15 +55,21 @@ declare -A BCMDS=( [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install' ) # } +# sessions that provide their own super bind and set the wallpaper { +declare SELF_CONTAINED='plasma|gnome|cinnamon|deepin' +declare SELF_CONTAINED_SES='startplasma-x11|gnome-session|startdde|cinnamon-session' +# } + # executable name for each wm/de used in ~/.xinitrc { declare -A WM_SESSIONS=( -[dwm]='dwm' [jwm]='jwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startkde' [xfce4]='startxfce4' -[gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session' +[dwm]='dwm' [jwm]='jwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startplasma-x11' [xfce4]='startxfce4' +[deepin]='startdde' [gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session' ) # } # packages installed for each wm/de, most are depends of the skel packages { declare -A WM_EXT=( -[dwm]='' [jwm]='' [gnome]='' [cinnamon]='gnome-terminal' [plasma]='kdebase-meta' +[dwm]='nitrogen polkit-gnome gnome-keyring dunst lxappearance' [jwm]='' [deepin]='deepin-extra' +[gnome]='gnome-tweaks' [cinnamon]='gnome-terminal' [plasma]='kde-applications-meta powerdevil' [awesome]='archlabs-skel-awesome' [bspwm]='archlabs-skel-bspwm' [fluxbox]='archlabs-skel-fluxbox' [i3-gaps]='archlabs-skel-i3-gaps' [openbox]='archlabs-skel-openbox' [xfce4]='archlabs-skel-xfce4 xfce4-goodies' ) # } @@ -238,22 +244,22 @@ select_show() msg "Show Configuration" " ---------- PARTITION CONFIGURATION ------------ - Root Part: $ROOT_PART - Boot Part: ${BOOT_PART:-none} - Boot Device: ${BOOT_DEV:-none} - Swap Part/File: ${SWAP_PART:-none} - Swap Size: ${SWAP_SIZE:-none} + Root Part: $ROOT + Boot Part: ${BOOT:-none} + Boot Device: ${BOOT_D:-none} + Swap Part/File: ${SWAP:-none} + Swap Size: ${SWAP_S:-none} Extra Mounts: ${EXMNTS:-none} Mkinit Hooks: ${HOOKS:-none} - LVM used: ${LVM:-none} - LUKS used: ${LUKS:-none} + LVM used: ${LVM:-unused} + LUKS used: ${LUKS:-unused} ------------ SYSTEM CONFIGURATION ------------- - Locale: ${MYLOCALE:-none} + Locale: ${LOCALE:-none} Keymap: ${KEYMAP:-none} - Hostname: ${MYHOST:-none} + Hostname: ${NEWHOST:-none} Timezone: ${ZONE:-none}/${SUBZ:-none} Chroot cmd: ${USER_CMD:-none} @@ -276,9 +282,9 @@ select_show() select_login() { - AUTOLOGIN='' # no autologin unless using xinit + AUTOLOGIN='' - dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \ + dlg LOGIN_TYPE menu "Login" "\nSelect what kind of login management to use." \ "xinit" "Console login without a display manager" \ "ly" "TUI display manager with a ncurses-like interface" \ "lightdm" "Lightweight display manager with a gtk greeter" \ @@ -288,14 +294,19 @@ select_login() case $LOGIN_TYPE in gdm|sddm) EDIT_FILES[login]="" ;; ly) EDIT_FILES[login]="/etc/ly/config.ini" ;; - lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;; + lightdm) + LIGHTDM_GREETER='gtk-greeter' + EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" + local txt="\nBecause you chose to install deepin you can choose to use their greeter for lightdm\n\nUse the deepin greeter?\n" + [[ $INSTALL_WMS == *deepin* ]] && yesno "Greeter" "$txt" && LIGHTDM_GREETER="deepin-greeter" + ;; xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile" if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then - dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1 + dlg LOGIN_WM menu "Session" "$_login" $LOGIN_CHOICES || return 1 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}" fi [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}" - yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN='' + yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true ;; esac } @@ -312,8 +323,8 @@ select_config() bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \ mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1 ;; - 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;; - 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;; + 1) dlg NEWHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;; + 2) dlg LOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;; 3) ZONE='' SUBZ='' until [[ $ZONE && $SUBZ ]]; do dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break @@ -348,12 +359,12 @@ select_mkuser() until [[ $NEWUSER ]]; do tput cnorm dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \ - "Username:" 1 1 "${ans[0]}" 1 11 "$COLUMNS" 0 0 \ - "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \ - "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \ - "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \ - "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \ - "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2> "$ANS" || return 1 + "Username:" 1 1 "${ans[0]}" 1 11 "$COLUMNS" 0 0 \ + "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \ + "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \ + "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \ + "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \ + "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2> "$ANS" || return 1 mapfile -t ans <"$ANS" @@ -381,7 +392,7 @@ select_mkuser() select_keymap() { - dlg KEYMAP menu "Keyboard Layout" "$_keymap" \ + dlg KEYMAP menu "Keyboard" "$_keymap" \ us English cm English gb English au English gh English \ za English ng English ca French 'cd' French gn French \ tg French fr French de German at German ch German \ @@ -420,7 +431,7 @@ select_keymap() select_usercmd() { - dlg USER_CMD input "User Command" "$_usercmd" "$USER_CMD" nolimit + dlg USER_CMD input "Command" "$_usercmd" "$USER_CMD" nolimit } select_sessions() @@ -435,7 +446,8 @@ select_sessions() xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \ awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \ fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \ - plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \ + plasma "A KDE software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \ + deepin "The desktop environment of the Chinese Deepin Linux distribution." "$(ofn deepin "${INSTALL_WMS[*]}")" \ gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \ cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" @@ -564,7 +576,7 @@ select_packages() part_menu() { - no_bg_install || return 0 + is_bg_install || return 0 local device choice devhash devhash="$(lsblk -f | base64)" umount_dir "$MNT" @@ -644,24 +656,24 @@ part_auto() errshow 0 "parted -s $device mkpart $boot_type $boot_fs 1MiB 513MiB" || return 1 sleep 0.5 - BOOT_DEV="$device" - AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}') + BOOT_D="$device" + AUTO_BOOT=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}') if [[ $SYS == "BIOS" ]]; then - mkfs.ext4 -q "$AUTO_BOOT_PART" > /dev/null 2> "$ERR" - errshow 0 "mkfs.ext4 -q $AUTO_BOOT_PART" || return 1 + mkfs.ext4 -q "$AUTO_BOOT" > /dev/null 2> "$ERR" + errshow 0 "mkfs.ext4 -q $AUTO_BOOT" || return 1 else - mkfs.vfat -F32 "$AUTO_BOOT_PART" > /dev/null 2> "$ERR" - errshow 0 "mkfs.vfat -F32 $AUTO_BOOT_PART" || return 1 + mkfs.vfat -F32 "$AUTO_BOOT" > /dev/null 2> "$ERR" + errshow 0 "mkfs.vfat -F32 $AUTO_BOOT" || return 1 fi msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0 parted -s "$device" mkpart primary ext4 513MiB 100% > /dev/null 2> "$ERR" errshow 0 "parted -s $device mkpart primary ext4 513MiB 100%" || return 1 sleep 0.5 - AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')" - mkfs.ext4 -q "$AUTO_ROOT_PART" > /dev/null 2> "$ERR" - errshow 0 "mkfs.ext4 -q $AUTO_ROOT_PART" || return 1 + AUTO_ROOT="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')" + mkfs.ext4 -q "$AUTO_ROOT" > /dev/null 2> "$ERR" + errshow 0 "mkfs.ext4 -q $AUTO_ROOT" || return 1 sleep 0.5 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n" } @@ -773,9 +785,9 @@ part_find() part_swap() { - if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then - fallocate -l $SWAP_SIZE "$1" 2> "$ERR" - errshow 0 "fallocate -l $SWAP_SIZE $1" + if [[ $1 == "$MNT/swapfile" && $SWAP_S ]]; then + fallocate -l $SWAP_S "$1" 2> "$ERR" + errshow 0 "fallocate -l $SWAP_S $1" chmod 600 "$1" 2> "$ERR" errshow 0 "chmod 600 $1" fi @@ -788,17 +800,23 @@ part_swap() part_mount() { - local part="$1" mountp="${MNT}$2" fs="" - fs="$(lsblk -lno FSTYPE "$part")" - mkdir -p "$mountp" + local part="$1" + local mntpt="${MNT}$2" + shift 2 + local fs="$(lsblk -lno FSTYPE "$part")" - if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" && $part != "$AUTO_ROOT_PART" ]] && select_mntopts "$fs"; then - mount -o "$MNT_OPTS" "$part" "$mountp" > /dev/null 2>&1 + mkdir -p "$mntpt" + + if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT" && $part != "$AUTO_ROOT" ]] && select_mntopts "$fs"; then + mount -o "$MNT_OPTS" "$part" "$mntpt" > /dev/null 2> "$ERR" + errshow 0 "mount -o $MNT_OPTS $part $mntpt" || return 1 else - mount "$part" "$mountp" > /dev/null 2>&1 + mount "$part" "$mntpt" > /dev/null 2> "$ERR" + errshow 0 "mount $part $mntpt" || return 1 fi - part_mountconf "$part" "$mountp" || return 1 + msg "Mount Complete" "\nPartition $part mounted at $mntpt\n" 1 + part_countdec "$part" part_cryptlv "$part" return 0 @@ -806,12 +824,14 @@ part_mount() part_format() { - local part="$1" fs="$2" delay="$3" + local part="$1" + local fs="$2" + local delay="$3" + shift 3 msg "Format" "\nFormatting $part as $fs\n" 0 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" > /dev/null 2> "$ERR" errshow 0 "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1 - FORMATTED+="$part " sleep $delay } @@ -831,20 +851,20 @@ part_device() die 1 fi - [[ $1 ]] && BOOT_DEV="$DEVICE" + [[ $1 ]] && BOOT_D="$DEVICE" return 0 } part_bootdev() { - BOOT_DEV="${BOOT_PART%[1-9]}" - BOOT_PART_NUM="${BOOT_PART: -1}" - [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}" + BOOT_D="${BOOT%[1-9]}" + BOOT_NUM="${BOOT: -1}" + [[ $BOOT = /dev/nvme* ]] && BOOT_D="${BOOT%p[1-9]}" if [[ $SYS == 'UEFI' ]]; then - parted -s $BOOT_DEV set $BOOT_PART_NUM esp on > /dev/null 2>&1 + parted -s $BOOT_D set $BOOT_NUM esp on > /dev/null 2>&1 else - parted -s $BOOT_DEV set $BOOT_PART_NUM boot on > /dev/null 2>&1 + parted -s $BOOT_D set $BOOT_NUM boot on > /dev/null 2>&1 fi return 0 } @@ -895,25 +915,13 @@ part_cryptlv() part_countdec() { for pt; do - if (( COUNT > 0 )); then + if (( COUNT )); then PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")" (( COUNT-- )) fi done } -part_mountconf() -{ - if grep -qw "$1" /proc/mounts; then - msg "Mount Success" "\nPartition $1 mounted at $2\n" 1 - part_countdec "$1" - return 0 - else - msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2 - return 1 - fi -} - ############################################################################### # mounting menus # mount_menu is the entry point which calls all other functions @@ -922,24 +930,117 @@ part_mountconf() mount_menu() { msg "Mount Menu" "\nGathering device and partition information.\n" 1 - no_bg_install || return 0 + is_bg_install || return 0 lvm_detect umount_dir "$MNT" part_find 'part|lvm|crypt' || { SEL=2; return 1; } [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS - select_root_partition || { ROOT_PART=''; return 1; } - select_boot_partition || { BOOT_PART=''; return 1; } - if [[ $BOOT_PART ]]; then - part_mount "$BOOT_PART" "/boot" && SEP_BOOT=true || return 1 + select_root || { ROOT=''; return 1; } + select_boot || { BOOT=''; return 1; } + if [[ $BOOT ]]; then + part_mount "$BOOT" "/boot" || return 1 part_bootdev + SEP_BOOT=true fi select_swap || return 1 - select_extra_partitions || return 1 + select_extra || return 1 install_background return 0 } +select_boot() +{ + local pts dev size isize ptcount=0 + + if [[ -z $BOOT ]]; then + if [[ $AUTO_BOOT && -z $LVM && -z $LUKS ]]; then + BOOT="$AUTO_BOOT" + return 0 + fi + + if (( COUNT )); then + while read -r dev size; do # walk partition list and skip ones that are too small/big for boot + size_t="${size: -1:1}" + isize=${size:0:-1} + isize=${isize%.*} + [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); } + done <<< "$PARTS" + fi + + case "$SYS" in + UEFI) + case "$ptcount" in + 0) msg "EFI Boot Partition" "\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;; + 1) msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;; + *) dlg BOOT menu "EFI Partition" "$_uefi" $pts ;; + esac + [[ $BOOT ]] || return 1 + ;; + BIOS) + if [[ $LUKS && ! $LVM ]]; then + case "$ptcount" in + 0) msg "Boot Partition" "\nLUKS without LVM requires a separate boot partition.\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;; + 1) msg "Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;; + *) dlg BOOT menu "Boot Partition" "$_biosluks" $pts ;; + esac + [[ $BOOT ]] || return 1 + else + (( ptcount == 0 )) && return 0 + dlg BOOT menu "Boot Partition" "$_bios" "skip" "no separate boot" $pts + [[ -z $BOOT || $BOOT == "skip" ]] && { BOOT=''; return 0; } + fi + ;; + esac + fi + + if ([[ $SYS == 'BIOS' ]] && grep -q 'ext[34]' <<< "$(fsck -N "$BOOT")") || ([[ $SYS == 'UEFI' ]] && grep -q 'fat' <<< "$(fsck -N "$BOOT")"); then + yesno "Format Boot Partition" "\nIMPORTANT:\n\nThe boot partition $BOOT $_format" "Format $BOOT" "Skip Formatting" 1 || return 0 + fi + + case "$SYS" in + UEFI) part_format "$BOOT" "vfat" 2 || return 1 ;; + BIOS) part_format "$BOOT" "ext4" 2 || return 1 ;; + esac + return 0 +} + +select_root() +{ + if [[ -z $ROOT ]]; then + if [[ $AUTO_ROOT && -z $LVM && -z $LUKS ]]; then + ROOT="$AUTO_ROOT" + msg "Mount Menu" "\nUsing partitions created during automatic format.\n" 2 + part_mount "$ROOT" || { ROOT=''; return 1; } + return 0 # we're done here + else + local pts dev size isize 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 (( ptcount == 1 )); then # only one available device + msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2 + ROOT="$(awk 'NF > 0 {print $1}' <<< "$pts")" + else + local txt="\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 4G will not be shown here." + dlg ROOT menu "Mount Root" "$txt" $pts + fi + fi + fi + + [[ $ROOT ]] && select_filesystem "$ROOT" && part_mount "$ROOT" "" && return 0 + + # should never reach here unless an error occurred + ROOT='' + return 1 +} + select_swap() { local pts dev size isize @@ -953,179 +1054,32 @@ select_swap() done <<< "$PARTS" fi - dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \ + dlg SWAP menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \ "none" "Don't allocate any swap space" \ "swapfile" "Allocate $SYS_MEM at /swapfile" \ $pts - if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then - SWAP_PART='' + if [[ -z $SWAP || $SWAP == "none" ]]; then + SWAP='' return 0 - elif [[ $SWAP_PART == "swapfile" ]]; then + elif [[ $SWAP == "swapfile" ]]; then local i=0 - until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do - (( i > 0 )) && msg "Swap Size Error" "\nSwap size must be 1(M|G) or greater, and can only contain whole numbers\n\nSize entered: $SWAP_SIZE\n" 2 - dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; } + until [[ ${SWAP_S:0:1} =~ [1-9] && ${SWAP_S: -1} =~ (M|G) ]]; do + (( i > 0 )) && msg "Swap Size Error" "\nSwap size must be 1(M|G) or greater, and can only contain whole numbers\n\nSize entered: $SWAP_S\n" 2 + dlg SWAP_S input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP=''; SWAP_S=''; return 1; } (( i++ )) done - part_swap "$MNT/$SWAP_PART" - SWAP_PART="/$SWAP_PART" - elif [[ $PARTS == *"$SWAP_PART"* ]]; then - part_swap $SWAP_PART - part_countdec $SWAP_PART - SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)" + part_swap "$MNT/$SWAP" + SWAP="/$SWAP" else - return 1 - fi - - return 0 -} - -select_mntopts() -{ - local fs="$1" opts='' - local title="${fs^} Mount Options" - - for i in ${FS_OPTS[$fs]}; do - opts+="$i - off " - done - - until [[ $MNT_OPTS ]]; do - dlg MNT_OPTS check "$title" "$_mount" $opts - [[ $MNT_OPTS ]] || return 1 - MNT_OPTS="${MNT_OPTS// /,}" - yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS='' - done - - return 0 -} - -select_mountpoint() -{ - EXMNT='' - until [[ $EXMNT ]]; do - dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1 - if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then - msg "Mountpoint Error" "$_errexpart" - EXMNT='' - fi - done - return 0 -} - -select_filesystem() -{ - local part="$1" fs='' cur='' - local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4" - cur="$(lsblk -lno FSTYPE "$part" 2> /dev/null)" - - # bail early if the partition was created in part_auto() - [[ $cur && $part == "$AUTO_ROOT_PART" ]] && return 0 - - until [[ $fs ]]; do - if [[ $cur && $part != "$ROOT_PART" ]]; then - dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1 - else - dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1 - fi - [[ $fs == 'skip' ]] && return 0 - yesno "Filesystem" "\nFormat $part as $fs?\n" || fs='' - done - part_format "$part" "$fs" 0 -} - -select_boot_partition() -{ - local pts dev size isize ptcount=0 - - if [[ -z $BOOT_PART ]]; then - if [[ $AUTO_BOOT_PART && -z $LVM && -z $LUKS ]]; then - BOOT_PART="$AUTO_BOOT_PART" - return 0 - else - if (( COUNT )); then - while read -r dev size; do # walk partition list and skip ones that are too small/big for boot - size_t="${size: -1:1}" - isize=${size:0:-1} - isize=${isize%.*} - [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); } - done <<< "$PARTS" - fi - - case "$SYS" in - UEFI) - case "$ptcount" in - 0) msg "EFI Boot Partition" "\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;; - 1) msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;; - *) dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts ;; - esac - [[ $BOOT_PART ]] || return 1 - ;; - BIOS) - if [[ $LUKS && ! $LVM ]]; then - case "$ptcount" in - 0) msg "Boot Partition" "\nLUKS without LVM requires a separate boot partition.\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;; - 1) msg "Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;; - *) dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts ;; - esac - [[ $BOOT_PART ]] || return 1 - else - (( ptcount == 0 )) && return 0 - dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "no separate boot" $pts - [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; } - fi - ;; - esac - fi - fi - - if ([[ $SYS == 'BIOS' ]] && grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")") || ([[ $SYS == 'UEFI' ]] && grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"); then - yesno "Format Boot Partition" "\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format" "Format $BOOT_PART" "Skip Formatting" 1 || return 0 - fi - - case "$SYS" in - UEFI) part_format "$BOOT_PART" "vfat" 2 || return 1 ;; - BIOS) part_format "$BOOT_PART" "ext4" 2 || return 1 ;; - esac - return 0 -} - -select_root_partition() -{ - if [[ -z $ROOT_PART ]]; then - if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then - ROOT_PART="$AUTO_ROOT_PART" - msg "Mount Menu" "\nUsing partitions created during automatic format.\n" 2 - part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; } - return 0 # we're done here - else - local pts dev size isize 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 (( ptcount == 1 )); then # only one available device - msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2 - ROOT_PART="$(awk 'NF > 0 {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." $pts - fi - fi - fi - - if [[ -z $ROOT_PART ]] || ! select_filesystem "$ROOT_PART" || ! part_mount "$ROOT_PART"; then - ROOT_PART='' - return 1 + part_swap "$SWAP" + part_countdec "$SWAP" + SWAP_S="$(lsblk -lno SIZE $SWAP)" fi return 0 } -select_extra_partitions() +select_extra() { local part dev size @@ -1148,10 +1102,65 @@ select_extra_partitions() return 1 fi done + (( COUNT == 0 )) && msg "Mount Extra" "\nMounting Finished\n\n\nNo extra partitions available to mount, returning to main menu.\n" 2 return 0 } +select_mntopts() +{ + local fs="$1" + local opts='' + local title="${fs^} Mount Options" + + for i in ${FS_OPTS[$fs]}; do + opts+="$i - off " + done + + until [[ $MNT_OPTS ]]; do + dlg MNT_OPTS check "$title" "$_mount" $opts + [[ $MNT_OPTS ]] || return 1 + MNT_OPTS="${MNT_OPTS// /,}" + yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS='' + done + return 0 +} + +select_filesystem() +{ + local part="$1" + local fs='' + local cur="$(lsblk -lno FSTYPE "$part" 2> /dev/null)" + local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4" + + # bail early if the partition was created in part_auto() + [[ $cur && $part == "$AUTO_ROOT" ]] && return 0 + + until [[ $fs ]]; do + if [[ $cur && $part != "$ROOT" ]]; then + dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1 + else + dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1 + fi + [[ $fs == 'skip' ]] && return 0 + yesno "Filesystem" "\nFormat $part as $fs?\n" || fs='' + done + part_format "$part" "$fs" 0 +} + +select_mountpoint() +{ + EXMNT='' + until [[ $EXMNT ]]; do + dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1 + if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then + msg "Mountpoint Error" "$_errexpart" + EXMNT='' + fi + done + return 0 +} + ############################################################################### # installation # main is the entry point which calls all other install functions, once @@ -1164,8 +1173,7 @@ install_main() errshow 1 "genfstab -U $MNT > $MNT/etc/fstab" [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" "$MNT/etc/fstab" install_packages - # tear free configs, MUST be done after package install for nvidia - [[ $TEARFREE ]] && install_tearfree_conf "$MNT/etc/X11/xorg.conf.d" + install_tearfree "$MNT/etc/X11/xorg.conf.d" install_mkinitcpio install_boot chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa" @@ -1211,13 +1219,16 @@ install_main() install_base() { + local msg oldmsg + clear tput cnorm - while kill -0 $BG_PID 2> /dev/null; do - clear; printf "\nA background install process is still running...\n"; sleep 1 - done - trap - EXIT - unset BG_PID + if [[ $BG_PID ]] && kill -0 $BG_PID 2> /dev/null; then + printf "\nA background install process is still running, tailing the output...\n" + tail -f --pid=$BG_PID "$BG" + trap - EXIT + unset BG_PID + fi # archiso files rm -rf "$MNT/etc/mkinitcpio-archiso.conf" @@ -1245,9 +1256,9 @@ install_base() [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf "$MNT/etc/" [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections "$MNT/etc/NetworkManager/" - echo "LANG=$MYLOCALE" > "$MNT/etc/locale.conf" + echo "LANG=$LOCALE" > "$MNT/etc/locale.conf" cp -fv "$MNT/etc/locale.conf" "$MNT/etc/default/locale" - sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" "$MNT/etc/locale.gen" + sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${LOCALE}/${LOCALE}/g" "$MNT/etc/locale.gen" chrun "locale-gen" chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime" @@ -1271,10 +1282,10 @@ install_base() EOF printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > "$MNT/etc/vconsole.conf" - echo "$MYHOST" > "$MNT/etc/hostname" + echo "$NEWHOST" > "$MNT/etc/hostname" cat > "$MNT/etc/hosts" <<- EOF 127.0.0.1 localhost - 127.0.1.1 $MYHOST + 127.0.1.1 $NEWHOST ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters @@ -1285,12 +1296,12 @@ install_boot() { echo "Installing $BOOTLDR" - if [[ $ROOT_PART == /dev/mapper* ]]; then - ROOT_PART_ID="$ROOT_PART" + if [[ $ROOT == /dev/mapper* ]]; then + ROOT_ID="$ROOT" else local uuid_type="UUID" [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID" - ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)" + ROOT_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT)" fi if [[ $SYS == 'UEFI' ]]; then @@ -1317,7 +1328,8 @@ install_boot() case "$BOOTLDR" in grub) cp -fv "$MNT/boot/EFI/$DIST/grubx64.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;; syslinux) cp -rf "$MNT/boot/EFI/syslinux/"* "$MNT/boot/EFI/BOOT/" && cp -f "$MNT/boot/EFI/syslinux/syslinux.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;; - refind-efi) sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' "$MNT/boot/EFI/refind/refind.conf" + refind-efi) + sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' "$MNT/boot/EFI/refind/refind.conf" cp -fv "$MNT/boot/EFI/refind/refind_x64.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;; esac fi @@ -1347,71 +1359,61 @@ install_user() chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2> "$ERR" 2>&1 errshow 1 "set $NEWUSER password" - if [[ $INSTALL_WMS == *dwm* ]]; then - install_suckless "/home/$NEWUSER" chroot - [[ $INSTALL_WMS == 'dwm' ]] && rm -rf "$MNT/home/$NEWUSER/.config/xfce4" - fi - [[ $INSTALL_WMS == *jwm* ]] && sed '7,14d; s/xlock -mode blank/i3-lock-fancy -p/g; s/root:1/rofi_run/g' "$MNT/etc/system.jwmrc" > "$MNT/home/$NEWUSER/.jwmrc" - [[ $INSTALL_WMS =~ (bspwm|openbox) ]] || rm -rf "$MNT/home/$NEWUSER/.config/"{jgmenu,tint2} - [[ $USER_PKGS != *geany* ]] && rm -rf "$MNT/home/$NEWUSER/.config/geany" - [[ $MYSHELL != 'bash' ]] && rm -rf "$MNT/home/$NEWUSER/.bash"* - [[ $MYSHELL != 'zsh' ]] && rm -rf "$MNT/home/$NEWUSER/.z"* + [[ $INSTALL_WMS == *dwm* ]] && install_suckless "/home/$NEWUSER" chroot - # remove some commands from ~/.xprofile when using KDE or Gnome as the login session - if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ (plasma|gnome)) ]]; then - sed -i '/super/d; /nitrogen/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile" - elif [[ $LOGIN_WM == 'dwm' ]]; then # and dwm - sed -i '/super/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile" - fi + install_cleanup "$NEWUSER" return 0 } install_login() { - local serv="$MNT/etc/systemd/system/getty@tty1.service.d" + AUTOLOGIN_SERV="$MNT/etc/systemd/system/getty@tty1.service.d" + + if [[ -z $LOGIN_TYPE ]]; then + rm -rf "$AUTOLOGIN_SERV" + return 0 + fi + + echo "Setting up $LOGIN_TYPE" + + if [[ $LOGIN_TYPE != 'xinit' ]]; then + [[ $INSTALL_WMS == *dwm* ]] && dwm_xsession + rm -rf "$AUTOLOGIN_SERV" "$MNT/home/$NEWUSER/.xinitrc" + chrun "systemctl enable $LOGIN_TYPE.service" 2> "$ERR" 2>&1 + errshow 1 "systemctl enable $LOGIN_TYPE.service" + fi + + ${LOGIN_TYPE}_config +} + +install_cleanup() +{ + local user="$1" + + # remove tint2 and jgmenu configs if bspwm and openbox aren't being installed + [[ $INSTALL_WMS =~ (bspwm|openbox) ]] || rm -rf "$MNT/home/$user/.config/"{jgmenu,tint2} + + # remove geany configs if it wasn't installed + [[ $USER_PKGS != *geany* ]] && rm -rf "$MNT/home/$user/.config/geany" + + # remove shell stuff for unused shells + [[ $MYSHELL != 'bash' ]] && rm -rf "$MNT/home/$user/.bash"* + [[ $MYSHELL != 'zsh' ]] && rm -rf "$MNT/home/$user/.z"* + + # cleanup default jwmrc + if [[ $INSTALL_WMS == *jwm* ]]; then + sed '7,14d; s/xlock -mode blank/i3-lock-fancy -p/g; s/root:1/rofi_run/g' "$MNT/etc/system.jwmrc" > "$MNT/home/$user/.jwmrc" + fi + + # no picom (compton) or ksuperkey in dwm only installs + [[ $LOGIN_WM == 'dwm' ]] && sed -i '/super/d; /picom/d' "$MNT/home/$user/.xprofile" "$MNT/root/.xprofile" + + # remove some commands from ~/.xprofile when using self contained sessions + if [[ $LOGIN_WM =~ ($SELF_CONTAINED_SES) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ ($SELF_CONTAINED)) ]]; then + sed -i '/super/d; /nitrogen/d; /picom/d' "$MNT/home/$user/.xprofile" "$MNT/root/.xprofile" + fi - case $LOGIN_TYPE in - ly|sddm|gdm|lightdm) - echo "Setting up $LOGIN_TYPE" - if [[ $LOGIN_WM == *dwm* ]]; then # dwm doesn't include an xsession file for display managers - mkdir -p "$MNT/usr/share/xsessions" - cat > "$MNT/usr/share/xsessions/dwm.desktop" <<- EOF - [Desktop Entry] - Encoding=UTF-8 - Name=Dwm - Comment=Dynamic Window Manager - Exec=dwm - Type=XSession - EOF - fi - rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc" - chrun "systemctl enable $LOGIN_TYPE.service" 2> "$ERR" 2>&1 - errshow 1 "systemctl enable $LOGIN_TYPE.service" - ${LOGIN_TYPE}_config - ;; - xinit) - echo "Setting up $LOGIN_TYPE" - if [[ $INSTALL_WMS ]]; then - sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc" - elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then - sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc" - return 0 - fi - if [[ $AUTOLOGIN ]]; then - sed -i "s/root/${NEWUSER}/g" "$serv/autologin.conf" - cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF - # automatically run startx when logging in on tty1 - [ \$XDG_VTNR -eq 1 ] && exec startx - EOF - else - rm -rf "$serv" - fi - ;; - *) - rm -rf "$serv" - ;; - esac } install_packages() @@ -1432,10 +1434,11 @@ install_packages() if [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox|jwm|awesome) ]]; then inpkg+="$WM_BASE_PKGS " elif [[ $INSTALL_WMS == 'dwm' ]]; then # dwm only needs a very limited package set - inpkg+="nitrogen polkit-gnome gnome-keyring dunst " + inpkg+=" " fi # update and install crucial packages first to avoid issues + al_repo "$MNT/etc/pacman.conf" chrun "pacman -Syyu $KERNEL $BASE_PKGS base-devel ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" 2> "$ERR" 2>&1 errshow 1 "pacman -Syyu $KERNEL $BASE_PKGS base-devel ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" @@ -1501,12 +1504,97 @@ install_suckless() fi } +install_tearfree() +{ + local xpath="$1" + + if [[ $VM ]]; then + echo "Virtual machine detected, removing xorg configs" + find "$xpath/" -name '*.conf' -delete -printf "remove %p\n" + elif [[ $TEARFREE ]]; then + if lspci | grep ' VGA ' | grep -q 'Intel'; then + echo "Creating Intel Tear Free config /etc/X11/xorg.conf.d/20-intel.conf" + cat > "$xpath/20-intel.conf" <<- EOF + Section "Device" + Identifier "Intel Graphics" + Driver "intel" + Option "TearFree" "true" + EndSection + EOF + cat "$xpath/20-intel.conf" + elif lspci | grep ' VGA ' | grep -q 'AMD/ATI.*RX\|AMD/ATI.*R[579]'; then # newer RX, R5, R7, and R9 cards can use the amdgpu driver + echo "Creating AMD Tear Free config /etc/X11/xorg.conf.d/20-amdgpu.conf" + cat > "$xpath/20-amdgpu.conf" <<- EOF + Section "Device" + Identifier "AMD Graphics" + Driver "amdgpu" + Option "TearFree" "true" + EndSection + EOF + cat "$xpath/20-amdgpu.conf" + elif lspci | grep ' VGA ' | grep -q 'AMD/ATI.*HD [2-6][0-9]*'; then # older HD 2xxx-6xxx cards must use the radeon driver + echo "Creating Radeon Tear Free config /etc/X11/xorg.conf.d/20-radeon.conf" + cat > "$xpath/20-radeon.conf" <<- EOF + Section "Device" + Identifier "AMD Graphics" + Driver "radeon" + Option "TearFree" "on" + EndSection + EOF + cat "$xpath/20-radeon.conf" + elif lspci | grep ' VGA ' | grep -q 'NVIDIA'; then # nvidia cards require a bit of checking for notebook gpus + echo "Trying nvidia driver install" + if lspci | grep ' VGA ' | grep -q 'Intel\|AMD' && lspci | grep ' VGA ' | grep -q 'NVIDIA.*[6-9][1-8][05]M[X]\?\|NVIDIA.*Quadro.*[KMP][1-6][0-2][0]*M'; then + if [[ $xpath == *"$MNT"* ]]; then + chrun "nvidia-installer --bumblebee" + else + nvidia-installer --bumblebee + fi + else + if [[ $xpath == *"$MNT"* ]]; then + chrun "nvidia-installer" # unsure which card so try auto detection + else + nvidia-installer + fi + fi + if [[ -e $xpath/20-nvidia.conf ]]; then + cat "$xpath/20-radeon.conf" + echo + echo "NVIDIA driver installed" + if [[ $xpath == *"$MNT"* ]]; then + echo "Trying to load the driver for live session" + nvidia-smi -r + fi + echo "To enable driver vsync:" + echo -e "\trun nvidia-settings (as root) on first boot\n\tenable 'ForceFullCompositionPipeline' under the advanced settings" + echo -e "\tlastly save the change to your nvida xorg config /etc/X11/xorg.conf.d/20-nvidia.conf" + echo -e "\tand remove everything but the Device and Screen sections from the file" + else + echo "Unable to install nvidia driver" + fi + return 0 + fi + + if lspci | grep ' VGA ' | grep -q 'Intel\|AMD/ATI'; then + if [[ $xpath == *"$MNT"* ]]; then + sed -i 's/xrender/glx/g' "$MNT/etc/skel/.config/picom.conf" + else + sed -i 's/xrender/glx/g' /etc/skel/.config/picom.conf + fi + fi + fi + + # remove nvidia installer from installed system when not running nvidia gpu + [[ $xpath == *"$MNT"* ]] && rm -rf "$MNT/usr/bin/nvidia-installer" "$MNT/var/lib/nvidia-installer" +} + install_mkinitcpio() { local add='' - [[ $LUKS ]] && add="encrypt" - [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; } - sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" "$MNT/etc/mkinitcpio.conf" + + [[ $LUKS ]] && add+=" encrypt" + [[ $LVM ]] && add+=" lvm2" + sed -i "s/block filesystems/block${add} filesystems ${HOOKS}/g" "$MNT/etc/mkinitcpio.conf" chrun "mkinitcpio -p $KERNEL" 2> "$ERR" 2>&1 errshow 1 "mkinitcpio -p $KERNEL" } @@ -1516,7 +1604,7 @@ install_mirrorlist() if hash reflector > /dev/null 2>&1; then reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1" elif hash rankmirrors > /dev/null 2>&1; then - echo "Sorting mirrorlist" + echo "Sorting mirrorlist... This will take a while" local key="access_key=5f29642060ab983b31fdf4c2935d8c56" ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")" country="$(curl -fsSL "http://api.ipstack.com/$ip_add?$key&fields=country_code" | python -c "import sys, json; print(json.load(sys.stdin)['country_code'])")" @@ -1539,97 +1627,20 @@ install_mirrorlist() install_background() { - ( rsync -a /run/archiso/sfs/airootfs/ "$MNT/" && install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" > /dev/null 2>&1 ) & + ( + rsync -a /run/archiso/sfs/airootfs/ "$MNT/" && + install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" > /tmp/bgout 2>&1 && + al_repo "$MNT/etc/pacman.conf" && + chrun "pacman -Syyu $BASE_PKGS base-devel --noconfirm --needed" > /tmp/bgout 2>&1 + ) & BG_PID=$! trap "kill $BG_PID 2> /dev/null" EXIT } -install_tearfree_conf() -{ - local xpath="$1" - - if [[ $VM ]]; then - echo "Virtual machine detected, removing xorg configs" - find "$xpath/" -name '*.conf' -delete -printf "remove %p\n" - elif lspci | grep ' VGA ' | grep -q 'Intel'; then - echo "Creating Intel Tear Free config /etc/X11/xorg.conf.d/20-intel.conf" - cat > "$xpath/20-intel.conf" <<- EOF - Section "Device" - Identifier "Intel Graphics" - Driver "intel" - Option "TearFree" "true" - EndSection - EOF - cat "$xpath/20-intel.conf" - elif lspci | grep ' VGA ' | grep -q 'AMD/ATI.*RX\|AMD/ATI.*R[579]'; then # newer RX, R5, R7, and R9 cards can use the amdgpu driver - echo "Creating AMD Tear Free config /etc/X11/xorg.conf.d/20-amdgpu.conf" - cat > "$xpath/20-amdgpu.conf" <<- EOF - Section "Device" - Identifier "AMD Graphics" - Driver "amdgpu" - Option "TearFree" "true" - EndSection - EOF - cat "$xpath/20-amdgpu.conf" - elif lspci | grep ' VGA ' | grep -q 'AMD/ATI.*HD [2-6][0-9]*'; then # older HD 2xxx-6xxx cards must use the radeon driver - echo "Creating Radeon Tear Free config /etc/X11/xorg.conf.d/20-radeon.conf" - cat > "$xpath/20-radeon.conf" <<- EOF - Section "Device" - Identifier "AMD Graphics" - Driver "radeon" - Option "TearFree" "on" - EndSection - EOF - cat "$xpath/20-radeon.conf" - elif lspci | grep ' VGA ' | grep -q 'NVIDIA'; then # nvidia cards require a bit of checking for notebook gpus - echo "Trying nvidia driver install" - if lspci | grep ' VGA ' | grep -q 'Intel\|AMD' && lspci | grep ' VGA ' | grep -q 'NVIDIA.*[6-9][1-8][05]M[X]\?\|NVIDIA.*Quadro.*[KMP][1-6][0-2][0]*M'; then # optimus - if [[ $xpath == *"$MNT"* ]]; then - chrun "nvidia-installer --bumblebee" - else - nvidia-installer --bumblebee - fi - else - if [[ $xpath == *"$MNT"* ]]; then - chrun "nvidia-installer" # unsure which card so try auto detection - else - nvidia-installer - fi - fi - if [[ -e $xpath/20-nvidia.conf ]]; then - cat "$xpath/20-radeon.conf" - echo - echo "NVIDIA driver installed" - if [[ $xpath == *"$MNT"* ]]; then - echo "Trying to load the driver for live session" - nvidia-smi -r - fi - echo "To enable driver vsync:" - echo -e "\trun nvidia-settings (as root) on first boot\n\tenable 'ForceFullCompositionPipeline' under the advanced settings" - echo -e "\tlastly save the change to your nvida xorg config /etc/X11/xorg.conf.d/20-nvidia.conf" - echo -e "\tand remove everything but the Device and Screen sections from the file" - else - echo "Unable to install nvidia driver" - fi - return 0 - fi - - if lspci | grep ' VGA ' | grep -q 'Intel\|AMD/ATI'; then - if [[ $xpath == *"$MNT"* ]]; then - sed -i 's/xrender/glx/g' "$MNT/etc/skel/.config/compton.conf" - else - sed -i 's/xrender/glx/g' /etc/skel/.config/compton.conf - fi - fi - - # remove nvidia installer from installed system when not running nvidia gpu - [[ $xpath == *"$MNT"* ]] && rm -rf "$MNT/usr/bin/nvidia-installer" "$MNT/var/lib/nvidia-installer" -} - ############################################################################### # display manager config # these are called based on which DM is chosen after it is installed -# additional config can be handled here, for now only lightdm has one +# additional config can be handled here, for now only lightdm and xinit. ly_config() { @@ -1646,17 +1657,51 @@ sddm_config() : #TODO } +xinit_config() +{ + if [[ $INSTALL_WMS ]]; then + sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc" + if [[ $LOGIN_WM == 'gnome-session' ]]; then + # see https://wiki.archlinux.org/index.php/GNOME#Manually + sed -i '/exec/ i export XDG_SESSION_TYPE=x11' "$MNT/home/$NEWUSER/.xinitrc" + sed -i '/exec/ i export GDK_BACKEND=x11' "$MNT/home/$NEWUSER/.xinitrc" + fi + else + rm -rf "$MNT/home/$NEWUSER/.xinitrc" "$MNT/root/.xinitrc" + return 0 + fi + + if [[ $AUTOLOGIN ]]; then + mkdir -p "$AUTOLOGIN_SERV" + cat > "$AUTOLOGIN_SERV/autologin.conf" <<- EOF + [Service] + ExecStart= + ExecStart=-/sbin/agetty --autologin $NEWUSER --noclear %I 38400 linux + EOF + cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF + # automatically run startx when logging in on tty1 + [ \$XDG_VTNR -eq 1 ] && exec startx + EOF + else + rm -rf "$AUTOLOGIN_SERV" + fi +} + lightdm_config() { - cat > "$MNT/etc/lightdm/lightdm-gtk-greeter.conf" <<- EOF - [greeter] - default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png - background=/usr/share/backgrounds/archlabs/archlabs.jpg - theme-name=Adwaita-dark - icon-theme-name=Adwaita - font-name=DejaVu Sans Mono 11 - position=30%,end 50%,end - EOF + sed -i "/greeter-session=/ c greeter-session=lightdm-$LIGHTDM_GREETER" "$MNT/etc/lightdm/lightdm.conf" + + if [[ $LIGHTDM_GREETER == 'gtk-greeter' ]]; then + cat > "$MNT/etc/lightdm/lightdm-gtk-greeter.conf" <<- EOF + [greeter] + default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png + background=/usr/share/backgrounds/archlabs/archlabs.jpg + theme-name=Adwaita-dark + icon-theme-name=Adwaita + font-name=DejaVu Sans Mono 11 + position=30%,end 50%,end + EOF + fi } ############################################################################### @@ -1670,8 +1715,8 @@ setup_grub() EDIT_FILES[bootloader]="/etc/default/grub" if [[ $SYS == 'BIOS' ]]; then - [[ $BOOT_DEV ]] || { part_device 1 || return 1; } - BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV" + [[ $BOOT_D ]] || { part_device 1 || return 1; } + BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_D" else BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1 grub-install --recheck --force --target=x86_64-efi --efi-directory=/boot --bootloader-id=$DIST" @@ -1718,8 +1763,8 @@ setup_efistub() prerun_efistub() { BCMDS[efistub]="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'" + efibootmgr -v -d $BOOT_D -p $BOOT_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \ + -u 'root=$ROOT_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'" } setup_syslinux() @@ -1729,7 +1774,7 @@ setup_syslinux() else 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" + efibootmgr -v -c -d $BOOT_D -p $BOOT_NUM -l /EFI/syslinux/syslinux.efi -L $DIST" fi } @@ -1779,13 +1824,13 @@ prerun_syslinux() LABEL $DIST MENU LABEL $DIST Linux LINUX $d/vmlinuz-$KERNEL - APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw + APPEND root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img LABEL ${DIST}fallback MENU LABEL $DIST Linux Fallback LINUX $d/vmlinuz-$KERNEL - APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw + APPEND root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img EOF return 0 @@ -1800,10 +1845,10 @@ setup_refind-efi() prerun_refind-efi() { cat > "$MNT/boot/refind_linux.conf" <<- EOF - "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && + "$DIST Linux" "root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] && printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img" - "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && + "$DIST Linux Fallback" "root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] && printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img" EOF @@ -1839,13 +1884,13 @@ prerun_systemd-boot() title $DIST Linux linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img") initrd /initramfs-$KERNEL.img - options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw + options root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw EOF cat > "$MNT/boot/loader/entries/$DIST-fallback.conf" <<- EOF title $DIST Linux Fallback linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img") initrd /initramfs-$KERNEL-fallback.img - options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw + options root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw EOF mkdir -p "$MNT/etc/pacman.d/hooks" cat > "$MNT/etc/pacman.d/hooks/systemd-boot.hook" <<- EOF @@ -1868,7 +1913,7 @@ prerun_systemd-boot() lvm_menu() { - no_bg_install || return 1 + is_bg_install || return 1 lvm_detect local choice while :; do @@ -1940,12 +1985,26 @@ lvm_lv_size() done if (( ERR_SIZE != 1 )); then case ${VOLUME_SIZE:$lv:1} in - [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000)) + [mMgG]) + local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000)) case ${VOLUME_SIZE:$lv:1} in - [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;; - [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;; + [Gg]) + if (( m >= VGROUP_MB )); then + ERR_SIZE=1 + else + VGROUP_MB=$((VGROUP_MB - m)) + fi + ;; + [Mm]) + if (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )); then + ERR_SIZE=1 + else + VGROUP_MB=$((VGROUP_MB - s)) + fi + ;; *) ERR_SIZE=1 - esac ;; + esac + ;; *) ERR_SIZE=1 esac fi @@ -2080,7 +2139,7 @@ lvm_volume_name() luks_menu() { local choice - no_bg_install || return 1 + is_bg_install || return 1 dlg choice menu "LUKS Encryption" "$_luksmenu" \ "$_luksnew" "cryptsetup -q luksFormat" \ "$_luksopen" "cryptsetup open --type luks" \ @@ -2159,8 +2218,8 @@ luks_setup() umount_dir "$MNT" part_find 'part|lvm' || return 1 - if [[ $AUTO_ROOT_PART ]]; then - LUKS_PART="$AUTO_ROOT_PART" + if [[ $AUTO_ROOT ]]; then + LUKS_PART="$AUTO_ROOT" elif (( COUNT == 1 )); then LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")" else @@ -2291,13 +2350,14 @@ live() echo "Sorting mirrorlist" mount /run/archiso/cowspace -o remount,size=2G install_mirrorlist "/etc/pacman.d/mirrorlist" + al_repo "/etc/pacman.conf" pacman -Syyu --noconfirm || die 1 rm -rf /var/cache/pacman/pkg/* pacman -S $BASE_PKGS $AL_BASE_PKGS xorg-xinit --needed --noconfirm || die 1 rm -rf /var/cache/pacman/pkg/* case "$ses" in i3-gaps|openbox|fluxbox|bspwm|awesome|xfce4|jwm) pacman -S "$ses" $WM_BASE_PKGS ${WM_EXT[$ses]} --needed --noconfirm || die 1 ;; - gnome|plasma|cinnamon) pacman -S "$ses" ${WM_EXT[$ses]} --needed --noconfirm || die 1 ;; + $SELF_CONTAINED) pacman -S "$ses" ${WM_EXT[$ses]} --needed --noconfirm || die 1 ;; dwm) { pacman -S git --needed --noconfirm || die 1; }; install_suckless "/root" nochroot ;; esac rm -rf /var/cache/pacman/pkg/* @@ -2305,10 +2365,10 @@ live() pacman -Scc --noconfirm rm -rf /var/cache/pacman/pkg/* cp -rfT /etc/skel /root - [[ $TEARFREE ]] && install_tearfree_conf "/etc/X11/xorg.conf.d" + install_tearfree "/etc/X11/xorg.conf.d" case "$ses" in - plasma|gnome|cinnamon) sed -i '/super/d; /nitrogen/d; /compton/d' /root/.xprofile ;; - dwm) sed -i '/super/d; /compton/d' /root/.xprofile ;; + $SELF_CONTAINED) sed -i '/super/d; /nitrogen/d; /picom/d' /root/.xprofile ;; + dwm) sed -i '/super/d; /picom/d' /root/.xprofile ;; esac rm -f /root/.zlogin echo -e "pulseaudio &\n(sleep 1; pamixer --unmute --set-volume 50) &" >> /root/.xprofile @@ -2350,9 +2410,9 @@ usage() root/boot partition: - set the ROOT_PART and/or BOOT_PART environment variables before launching the installer eg. + set the ROOT and/or BOOT environment variables before launching the installer eg. - ROOT_PART='/dev/sda2' BOOT_PART='/dev/sda1' $1 + ROOT='/dev/sda2' BOOT='/dev/sda1' $1 editor used: @@ -2391,6 +2451,26 @@ debug() DEBUG=true } +al_repo() +{ + local conf="$1" + + if ! grep -q 'archlabs_repo' "$conf"; then + cat >> "$conf" <<- EOF + + [archlabs_unstable] + Server = https://bitbucket.org/archlabslinux/\$repo/raw/master/\$arch + + [archlabs_repo] + Server = https://bitbucket.org/archlabslinux/\$repo/raw/master/\$arch + Server = https://sourceforge.net/projects/archlabs-repo/files/\$repo/\$arch + Server = https://github.com/ARCHLabs/\$repo/raw/master/\$arch + + EOF + fi + return 0 +} + termcol() { local colors=( @@ -2499,7 +2579,20 @@ net_connect() fi } -no_bg_install() +dwm_xsession() +{ + mkdir -p "$MNT/usr/share/xsessions" + cat > "$MNT/usr/share/xsessions/dwm.desktop" <<- EOF + [Desktop Entry] + Encoding=UTF-8 + Name=Dwm + Comment=Dynamic Window Manager + Exec=dwm + Type=XSession + EOF +} + +is_bg_install() { [[ $BG_PID ]] || return 0 msg "Install Running" "\nA background install process is currently running.\n" 2 @@ -2554,7 +2647,11 @@ system_identify() # enable some nicer colours in the linux console termcol -if (( UID != 0 )); then +# ensure the required packages are installed and that we're running as root on x86_64 architecture +if ! hash dialog rsync find parted curl >/dev/null 2>&1; then + printf "One or more of the required packages is missing: dialog, curl, rsync, parted, findutils" + die 1 +elif (( UID != 0 )); then msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2 die 1 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then @@ -2587,7 +2684,8 @@ system_devices msg "Welcome to the $DIST Installer" "$_welcome" if ! select_keymap; then - clear; die 0 + clear + die 0 elif ! net_connect; then msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2 die 1