2822 lines
103 KiB
Bash
Executable File
2822 lines
103 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# This program is free software, provided under the GNU GPL
|
|
# Written by Nathaniel Maia for use in Archlabs
|
|
# Some ideas and code reworked from other resources
|
|
# AIF, Calamares, and the Arch Wiki.. Credit where credit is due
|
|
|
|
# shellcheck disable=SC2086,SC2046
|
|
|
|
VER=2.1.30
|
|
|
|
# default values {
|
|
|
|
: "${DIST=ArchLabs}" # distro name if not set
|
|
: "${MNT=/mnt}" # installation root mountpoint if not set
|
|
ANS=/tmp/ans # dialog answer output file
|
|
FONT=ter-i16n # font used for the linux console
|
|
HOOKS=shutdown # additional mkinitcpio HOOKS
|
|
SEL=0 # currently selected menu item
|
|
PACSTRAP=1 # use a fresh pacstrap or copy the iso filesystem
|
|
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
|
|
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`
|
|
|
|
typeset -a PACKAGES USER_PKGS
|
|
|
|
# packages installed for all installation types as a baseline
|
|
typeset -a BASE_PKGS=(
|
|
"base" "base-devel" "xorg" "xorg-drivers" "sudo" "git" "gvfs" "gtk3"
|
|
"libmad" "libmatroska" "tumbler" "ffmpeg" "gstreamer" "gst-libav" "pamixer"
|
|
"gst-plugins-base" "scrot" "gst-plugins-good" "bash-completion" "xterm"
|
|
"playerctl" "pulseaudio" "pulseaudio-alsa" "pavucontrol" "xdg-user-dirs"
|
|
)
|
|
|
|
# packages installed specific to archlabs, installed when any session is chosen
|
|
typeset -a AL_PKGS=(
|
|
"archlabs-keyring" "archlabs-icons" "archlabs-fonts" "archlabs-themes"
|
|
"archlabs-baph" "archlabs-wallpapers" "archlabs-scripts" "archlabs-skel-base"
|
|
)
|
|
|
|
# packages installed for most window managers to provide some basic functionality
|
|
typeset -a WM_PKGS=(
|
|
"arandr" "nitrogen" "polkit-gnome" "network-manager-applet" "feh"
|
|
"volumeicon" "xclip" "exo" "laptop-detect" "xdotool" "picom" "wmctrl"
|
|
"gnome-keyring" "dunst" "gsimplecal" "xfce4-power-manager" "xfce4-settings"
|
|
)
|
|
|
|
# packages installed when choosing to use pacstrap
|
|
typeset -a ISO_PKGS=(
|
|
"arch-install-scripts" "b43-firmware" "b43-fwcutter" "broadcom-wl" "btrfs-progs"
|
|
"clonezilla" "crda" "darkhttpd" "ddrescue" "dhclient" "dhcpcd" "dialog" "diffutils"
|
|
"dmraid" "dnsmasq" "dnsutils" "dosfstools" "elinks" "ethtool" "exfat-utils" "f2fs-tools"
|
|
"fsarchiver" "ppp" "pptpclient" "reiserfsprogs" "rp-pppoe" "rsync" "sdparm" "sg3_utils"
|
|
"smartmontools" "linux-firmware" "lsscsi" "lvm2" "man-db" "man-pages" "mc" "mdadm" "mtools"
|
|
"nano" "ndisc6" "netctl" "nfs-utils" "nilfs-utils" "nmap" "ntfs-3g" "ntp" "openconnect"
|
|
"openssh" "openvpn" "p7zip" "partclone" "parted" "partimage" "gpm" "gptfdisk" "hdparm"
|
|
"htop" "ipw2100-fw" "ipw2200-fw" "irssi" "iwd" "jfsutils" "iputils" "lftp" "linux-atm"
|
|
"gnu-netcat" "tcpdump" "testdisk" "unrar" "usb_modeswitch" "usbutils" "vi" "vim" "vpnc"
|
|
"wget" "wvdial" "wireless-regdb" "wireless_tools" "wpa_supplicant" "xfsprogs" "xl2tpd"
|
|
"alsa-firmware" "alsa-lib" "alsa-plugins" "geoclue2" "lsb-release" "networkmanager"
|
|
"pacman-contrib" "reflector" "terminus-font" "ttf-dejavu" "archlabs-keyring" "lm_sensors"
|
|
)
|
|
|
|
SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
|
|
LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
|
|
CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
|
|
|
|
[[ $LINES ]] || LINES=$(tput lines)
|
|
[[ $COLUMNS ]] || COLUMNS=$(tput cols)
|
|
|
|
# }
|
|
|
|
# commands used to install each bootloader, however most get modified during runtime {
|
|
declare -A BCMDS=(
|
|
[refind-efi]='refind-install'
|
|
[grub]='grub-install --recheck --force' [syslinux]='syslinux-install_update -i -a -m'
|
|
[efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install'
|
|
) # }
|
|
|
|
# sessions that provide their own super bind and set the wallpaper {
|
|
declare WM_PKG_SES='openbox|bspwm|i3-gaps|fluxbox|jwm|awesome'
|
|
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]='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]='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'
|
|
) # }
|
|
|
|
# files offered for editing after install is complete {
|
|
declare -A EDIT_FILES=(
|
|
[login]='' # login is populated once we know the username and shell
|
|
[fstab]='/etc/fstab' [sudoers]='/etc/sudoers' [crypttab]='/etc/crypttab' [pacman]='/etc/pacman.conf'
|
|
[console]='/etc/vconsole.conf' [mkinitcpio]='/etc/mkinitcpio.conf' [hostname]='/etc/hostname /etc/hosts'
|
|
[bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
|
|
[locale]='/etc/locale.conf /etc/default/locale' [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
|
|
) # }
|
|
|
|
# mkfs command flags for filesystem formatting {
|
|
declare -A FS_CMD_FLAGS=(
|
|
[f2fs]='-f' [jfs]='-q' [xfs]='-f' [ntfs]='-q' [ext2]='-q' [ext3]='-q' [ext4]='-q' [vfat]='-F32' [nilfs2]='-q' [reiserfs]='-q'
|
|
) # }
|
|
|
|
# mount options for each filesystem {
|
|
declare -A FS_OPTS=(
|
|
[vfat]='' [ntfs]='' [ext2]='' [ext3]='' # NA
|
|
[jfs]='discard errors=continue errors=panic nointegrity'
|
|
[reiserfs]='acl nolog notail replayonly user_xattr off'
|
|
[ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
|
|
[xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
|
|
[nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
|
|
[f2fs]='discard fastboot flush_merge data_flush inline_xattr inline_data noinline_data inline_dentry no_heap noacl nobarrier norecovery noextent_cache disable_roll_forward disable_ext_identify'
|
|
) # }
|
|
|
|
# packages installed for each login option {
|
|
declare -A LOGIN_PKGS=(
|
|
[xinit]='xorg-xinit' [ly]='archlabs-ly' [gdm]='gdm' [sddm]='sddm'
|
|
[lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
|
|
) # }
|
|
|
|
# extras installed for user selected packages {
|
|
# if a package requires additional packages that aren't already dependencies
|
|
# they can be added here eg. [package]="extra"
|
|
declare -A PKG_EXT=(
|
|
[vlc]='qt4' [mpd]='mpc' [mupdf]='mupdf-tools'
|
|
[zathura]='zathura-pdf-poppler' [noto-fonts]='noto-fonts-emoji' [cairo-dock]='cairo-dock-plug-ins' [qt5ct]='qt5-styleplugins'
|
|
[vlc]='qt5ct qt5-styleplugins' [qutebrowser]='qt5ct qt5-styleplugins' [qbittorrent]='qt5ct qt5-styleplugins' [transmission-qt]='qt5ct qt5-styleplugins'
|
|
[bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci' [kdenlive]='dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
|
|
) # }
|
|
|
|
# dialog text variables {
|
|
# Basics (somewhat in order)
|
|
_welcome="\nThis will help you get $DIST installed and setup on your system.\n\nIf you are unsure about a section the default option will be listed or\nthe first selected item will be the default.\n\n\nMenu Navigation:\n\n - Select items with the arrow keys or the option number.\n - Use [Space] to toggle check boxes and [Enter] to accept.\n - Switch between fields using [Tab] or the arrow keys.\n - Use [Page Up] and [Page Down] to jump whole pages\n - Press the highlighted key of an option to select it.\n"
|
|
_keymap="\nPick which keymap to use for the system from the list below\n\nThis is used once a graphical environment is running (Xorg).\n\nSystem default: us"
|
|
_vconsole="\nSelect the console keymap, the console is the tty shell you reach before starting a graphical environment (Xorg).\n\nIts keymap is separate from the one used by the graphical environments, though many do use the same such as 'us' English.\n\nSystem default: us"
|
|
_prep="\nThis is the installer main menu, once a step is complete you will return here.\n\nOn successful completion of a step the cursor will be advanced to the next step\nOn failure the cursor will be placed on the step required to advance (when possible).\n\nSteps beginning with an asterisk (*) are required.\n\nOnce you're happy with the choices and the required steps are complete, selecting the final step will begin the install."
|
|
_device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
|
|
_mount="\nUse [Space] to toggle mount options from below, press [Enter] when done to confirm selection.\n\nNot selecting any and confirming will run an automatic mount."
|
|
_warn="\nIMPORTANT: Choose carefully when editing, formatting, and mounting partitions or your DATA MAY BE LOST.\n\nTo mount a partition without formatting it, select 'skip' when prompted to choose a filesystem during the mounting stage.\nThis can only be used for partitions that already contain a filesystem and cannot be the root (/) partition, it needs to be formatted before install.\n"
|
|
_part="\nFull device auto partitioning is available for beginners otherwise cfdisk is recommended.\n\n - All systems will require a root partition (8G or greater).\n - UEFI or BIOS using LUKS without LVM require a separate boot partition (100-512M)."
|
|
_uefi="\nSelect the EFI boot partition (/boot), required for UEFI boot.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as vfat/fat32 if not already."
|
|
_bios="\nDo you want to use a separate boot partition? (optional)\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
|
|
_biosluks="\nSelect the boot partition (/boot), required for LUKS.\n\nIt's usually the first partition on the device, 100-512M, and will be formatted as ext3/4 if not already."
|
|
_format="is already formatted correctly.\n\nFor a clean install, previously existing partitions should be reformatted, however this removes ALL data (bootloaders) on the partition so choose carefully.\n\nDo you want to reformat the partition?\n"
|
|
_swapsize="\nEnter the size of the swapfile in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte swapfile, while 10G will create a 10 gigabyte swapfile.\n\nFor ease of use and as an example it is filled in to match the size of your system memory (RAM).\n\nMust be greater than 1, contain only whole numbers, and end with either M or G."
|
|
_expart="\nYou can now choose any additional partitions you want mounted, you'll be asked for a mountpoint after.\n\nSelect 'done' to finish the mounting step and begin unpacking the base system in the background."
|
|
_exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
|
|
_bginstall="\nA background install portion will now begin, select what kind of base install to use\n\npacstrap - guarantees the latest packages and avoids conflicts but is much slower and network dependant\n\ncopy iso - much faster and not network dependant but can have issues\n"
|
|
_user="\nEnter a name and password for the new user account.\n\nThe name must not use capital letters, contain any periods (.), end with a hyphen (-), or include any colons (:)\n\nNOTE: Use [Up], [Down], or [Tab] to switch between fields, and [Enter] to accept."
|
|
_hostname="\nEnter a hostname for the new system.\n\nA hostname is used to identify systems on the network.\n\nIt's restricted to alphanumeric characters (a-z, A-Z, 0-9).\nIt can contain hyphens (-) BUT NOT at the beginning or end."
|
|
_locale="\nLocale determines the system language and currency formats.\n\nThe format for locale names is languagecode_COUNTRYCODE\n\neg. en_US is: English United States\n en_GB is: English Great Britain"
|
|
_timez="\nSelect your timezone country or continent from the list below"
|
|
_timesubz="\nSelect your time zone city.\n\nTIP: Pressing a letter key repeatedly navigates between entries beginning with that letter."
|
|
_sessions="\nUse [Space] to toggle available sessions, use [Enter] to accept the selection and continue.\n\nA basic package set will be installed for compatibility and functionality."
|
|
_login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
|
|
_autologin="\nDo you want autologin enabled for USER?\n\nIf so the following two files will be created (disable autologin by removing them):\n\n - /home/USER/RC (run startx when logging in on tty1)\n - /etc/systemd/system/getty@tty1.service.d/autologin.conf (login USER without password)\n"
|
|
_packages="\nUse [Space] to toggle packages then press [Enter] to accept.\n\nPackages may be installed by your DE/WM (if any), or for the packages you select."
|
|
_usercmd="\nEnter command to be run in the newly installed system (chroot) below.\n\nAn example use case would be installing packages or editing files not offered in the menus.\n\nBecause the command will be run in a chroot not every command will function correctly, additionally the command will not be sanity checked, it's your system so exercise caution.\n\nMore than one command may be run using standard bash syntax.\n"
|
|
_edit="\nBefore exiting you can select configuration files to review/change.\n\nIf you need to make other changes with the drives still mounted, use Ctrl-z to pause the installer, when finished type 'fg' and [Enter] to resume the installer, if you want to avoid the automatic reboot using Ctrl-c will cleanly exit."
|
|
|
|
# LUKS
|
|
_luksnew="Basic LUKS Encryption"
|
|
_luksadv="Advanced LUKS Encryption"
|
|
_luksopen="Open Existing LUKS Partition"
|
|
_luksmenu="\nA separate boot partition without encryption or logical volume management (LVM) is required (except BIOS systems using grub).\n\nBasic uses the default encryption settings, and is recommended for beginners. Advanced allows cypher and key size parameters to be entered manually."
|
|
_luksomenu="\nEnter a name and password for the encrypted device.\n\nIt is not necessary to prefix the name with /dev/mapper/, an example has been provided."
|
|
_lukskey="Once the specified flags have been amended, they will automatically be used with the 'cryptsetup -q luksFormat /dev/...' command.\n\nNOTE: Do not specify any additional flags such as -v (--verbose) or -y (--verify-passphrase)."
|
|
|
|
# LVM
|
|
_lvmmenu="\nLogical volume management (LVM) allows 'virtual' hard drives (volume groups) and partitions (logical volumes) to be created from existing device partitions.\n\nA volume group must be created first, then one or more logical volumes within it.\n\nLVM can also be used with an encrypted partition to create multiple logical volumes (e.g. root and home) within it."
|
|
_lvmnew="Create Volume Group and Volume(s)"
|
|
_lvmdel="Delete an Existing Volume Group"
|
|
_lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
|
|
_lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
|
|
_lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
|
|
_lvmlvsize="\nEnter what size you want the logical volume (LV) to be in megabytes (M) or gigabytes (G).\n\neg. 100M will create a 100 megabyte volume, 10G will create a 10 gigabyte volume."
|
|
_lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
|
|
|
|
# Errors
|
|
_errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by at least one character.\n"
|
|
_errpart="\nYou need create the partition(s) first.\n\n\nBIOS systems require at least one partition (ROOT).\n\nUEFI systems require at least two (ROOT and EFI).\n"
|
|
_errchoice="\nIf you want to fix the issue yourself use Ctrl-z to pause the installer. From there you can do whatever is needed to resolve the error.\nOnce finished use the 'fg' command to resume the installer, then select 'Continue'.\n"
|
|
_lukserr="\nA minimum of two partitions are required for encryption:\n\n 1. root (/) - standard or LVM.\n 2. boot (/boot) - standard (unless using LVM on BIOS systems).\n"
|
|
_lvmerr="\nThere are no viable partitions available to use for LVM, a minimum of one is required.\n\nIf LVM is already in use, deactivating it will allow the partition(s) to be used again.\n"
|
|
_lvmerrvgname="\nInvalid name entered.\n\nThe volume group name may be alpha-numeric, but may not contain spaces, start with a '/', or already be in use.\n"
|
|
_lvmerlvname="\nInvalid name entered.\n\nThe logical volume (LV) name may be alpha-numeric, but may not contain spaces or be preceded with a '/'\n"
|
|
_lvmerrlvsize="\nInvalid value Entered.\n\nMust be a numeric value with 'M' (megabytes) or 'G' (gigabytes) at the end.\n\neg. 400M, 10G, 250G, etc...\n\nThe value may also not be equal to or greater than the remaining size of the volume group.\n"
|
|
|
|
# }
|
|
|
|
###############################################################################
|
|
# selection menus
|
|
# main is the entry point which calls functions including outside of its block
|
|
# once those functions finished they always are returned here with the
|
|
# exception of install_main(), it exits upon completion
|
|
|
|
main()
|
|
{
|
|
(( SEL < 13 )) && (( SEL++ ))
|
|
tput civis
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " \
|
|
--default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
|
|
1 "Show device tree" \
|
|
2 "Partitioning" \
|
|
3 "LUKS encryption" \
|
|
4 "Logical volume management" \
|
|
5 "* Mount partitions" \
|
|
6 "* Select bootloader" \
|
|
7 "* Username and password" \
|
|
8 "* System configuration" \
|
|
9 "Select window manager or desktop" \
|
|
10 "Select additional packages" \
|
|
11 "Run a command on the installed system" \
|
|
12 "View configuration and command selections" \
|
|
13 "* Confirm choices and start the installation" 2> "$ANS"
|
|
|
|
read -r SEL < "$ANS"
|
|
[[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
|
|
case $SEL in
|
|
1) part_show ;;
|
|
2) part_menu || (( SEL-- )) ;;
|
|
3) luks_menu || (( SEL-- )) ;;
|
|
4) lvm_menu || (( SEL-- )) ;;
|
|
5) mount_menu || (( SEL-- )) ;;
|
|
6) prechecks 0 && { select_bootldr || (( SEL-- )); } ;;
|
|
7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
|
|
8) prechecks 2 && { select_config || (( SEL-- )); } ;;
|
|
9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
|
|
10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
|
|
11) prechecks 3 && select_usercmd ;;
|
|
12) prechecks 3 && select_show ;;
|
|
13) prechecks 3 && install_main ;;
|
|
*) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
|
|
esac
|
|
}
|
|
|
|
select_show()
|
|
{
|
|
local pkgs="${USER_PKGS[*]} ${PACKAGES[*]}"
|
|
[[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
|
|
pkgs="${pkgs// / }" pkgs="${pkgs# }"
|
|
msg "Show Configuration" "
|
|
---------- PARTITION CONFIGURATION ------------
|
|
|
|
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:-unused}
|
|
LUKS used: ${LUKS:-unused}
|
|
|
|
------------ SYSTEM CONFIGURATION -------------
|
|
|
|
Locale: ${LOCALE:-none}
|
|
Keymap: ${KEYMAP:-none}
|
|
Hostname: ${NEWHOST:-none}
|
|
Timezone: ${ZONE:-none}/${SUBZ:-none}
|
|
|
|
Chroot cmd: ${USER_CMD:-none}
|
|
|
|
------------ USER CONFIGURATION ---------------
|
|
|
|
Username: ${NEWUSER:-none}
|
|
Login Shell: ${NEWSHELL:-none}
|
|
Login Session: ${LOGIN_WM:-none}
|
|
Autologin: ${AUTOLOGIN:-none}
|
|
Login Type: ${LOGIN_TYPE:-none}
|
|
|
|
----------- PACKAGE CONFIGURATION -------------
|
|
|
|
Kernel: ${KERNEL:-none}
|
|
Bootloader: ${BOOTLDR:-none}
|
|
Packages: ${pkgs:-none}
|
|
"
|
|
}
|
|
|
|
select_login()
|
|
{
|
|
AUTOLOGIN=''
|
|
|
|
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" \
|
|
"gdm" "Gnome display manager" \
|
|
"sddm" "Simple desktop display manager" || return 1
|
|
|
|
case $LOGIN_TYPE in
|
|
gdm|sddm) EDIT_FILES[login]="" ;;
|
|
ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
|
|
lightdm)
|
|
LIGHTDM_GREETER='gtk-greeter'
|
|
EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
|
|
local txt="\nWith a deepin install 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 "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
|
|
;;
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
select_config()
|
|
{
|
|
typeset -i i=0
|
|
CONFIG_DONE=''
|
|
|
|
until [[ $CONFIG_DONE ]]; do
|
|
case $i in
|
|
0) dlg NEWSHELL menu "Shell" "\nChoose which shell to use." \
|
|
zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
|
|
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 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
|
|
dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
|
|
done
|
|
[[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
|
|
4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
|
|
linux 'Vanilla linux kernel and modules, with a few patches applied' \
|
|
linux-lts 'Long-term support (LTS) linux kernel and modules' \
|
|
linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
|
|
linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
|
|
CONFIG_DONE=true
|
|
;;
|
|
esac
|
|
(( i++ )) # progress through to the next choice
|
|
done
|
|
|
|
case $NEWSHELL in
|
|
bash) LOGINRC='.bash_profile' ;;
|
|
zsh) LOGINRC='.zprofile' ;;
|
|
mksh) LOGINRC='.profile' ;;
|
|
esac
|
|
|
|
return 0
|
|
}
|
|
|
|
select_mkuser()
|
|
{
|
|
NEWUSER=''
|
|
typeset -a ans
|
|
|
|
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
|
|
|
|
mapfile -t ans <"$ANS"
|
|
|
|
# root passwords empty, so use the user passwords
|
|
if [[ -z "${ans[4]}" && -z "${ans[5]}" ]]; then
|
|
ans[4]="${ans[1]}"
|
|
ans[5]="${ans[2]}"
|
|
fi
|
|
|
|
# make sure a username was entered and that the passwords match
|
|
if [[ -z ${ans[0]} || ${ans[0]} =~ \ |\' || ${ans[0]} =~ [^a-z0-9] ]]; then
|
|
msg "Invalid Username" "\nInvalid user name.\n\nPlease try again.\n"; ans[0]=''
|
|
elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
|
|
msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
|
|
elif [[ "${ans[4]}" != "${ans[5]}" ]]; then
|
|
msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
|
|
else
|
|
NEWUSER="${ans[0]}"
|
|
USER_PASS="${ans[1]}"
|
|
ROOT_PASS="${ans[4]}"
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
select_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 \
|
|
es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
|
|
sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
|
|
sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
|
|
tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
|
|
la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
|
|
dk Danish be Belgian in Indian al Albanian am Armenian \
|
|
bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
|
|
hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
|
|
af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
|
|
kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
|
|
no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
|
|
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 \
|
|
me Montenegrin || return 1
|
|
|
|
if [[ $CMAPS == *"$KEYMAP "* ]]; then
|
|
CMAP="$KEYMAP"
|
|
else
|
|
dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
|
|
fi
|
|
|
|
if [[ $TERM == 'linux' ]]; then
|
|
loadkeys "$CMAP" > /dev/null 2>&1
|
|
else
|
|
setxkbmap "$KEYMAP" > /dev/null 2>&1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
select_usercmd()
|
|
{
|
|
dlg USER_CMD input "Command" "$_usercmd" "$USER_CMD" nolimit
|
|
}
|
|
|
|
select_bootldr()
|
|
{
|
|
if [[ $SYS == 'BIOS' ]]; then
|
|
dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
|
|
"grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
|
|
"syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
|
|
else
|
|
dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
|
|
"systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
|
|
"grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
|
|
"refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
|
|
"efistub" "Boot the kernel image directly (no chainloading support)" \
|
|
"syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
|
|
fi
|
|
setup_${BOOTLDR}
|
|
return 0
|
|
}
|
|
|
|
select_sessions()
|
|
{
|
|
LOGIN_CHOICES=''
|
|
dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
|
|
i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
|
|
openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
|
|
dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
|
|
bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
|
|
jwm "A lightweight window manager for Xorg written in C" "$(ofn jwm "${INSTALL_WMS[*]}")" \
|
|
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[*]}")" \
|
|
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[*]}")"
|
|
|
|
[[ $INSTALL_WMS ]] || return 0
|
|
for i in ${INSTALL_WMS/dwm/}; do
|
|
WM_PKGS+=("$i")
|
|
done
|
|
|
|
for i in $INSTALL_WMS; do
|
|
LOGIN_CHOICES+="$i - "
|
|
if [[ $i =~ (plasma|deepin) ]]; then
|
|
local txt="These are larger package groups containing applications that are a part of $i, but are not included in the $i package group."
|
|
yesno "${i^} Extra" \
|
|
"\nThere are some extra packages available for $i that you may want installed: ${WM_EXT[$i]}\n\n$txt\n\nWould you like to install them?\n" || continue
|
|
fi
|
|
if [[ ${WM_EXT[$i]} ]]; then
|
|
for j in ${WM_EXT[$i]}; do
|
|
[[ ${WM_PKGS[*]} != *"$j"* ]] && WM_PKGS+=("$j")
|
|
done
|
|
fi
|
|
done
|
|
|
|
select_login || return 1
|
|
|
|
for pkg in "${WM_PKGS[@]}"; do
|
|
[[ ${PACKAGES[*]} != *"$pkg"* ]] && PACKAGES+=("$pkg")
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
select_packages()
|
|
{
|
|
dlg UPKGS check " Packages " "$_packages" \
|
|
abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
|
|
alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
|
|
atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
|
|
audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
|
|
audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
|
|
blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
|
|
bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
|
|
cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
|
|
calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
|
|
chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
|
|
clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
|
|
cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
|
|
deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
|
|
deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
|
|
emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
|
|
epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
|
|
evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
|
|
evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
|
|
file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
|
|
firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
|
|
gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
|
|
geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
|
|
geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
|
|
gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
|
|
gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
|
|
gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
|
|
gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
|
|
gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
|
|
gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
|
|
gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
|
|
guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
|
|
hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
|
|
inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
|
|
irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
|
|
kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
|
|
krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
|
|
libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
|
|
lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
|
|
mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
|
|
mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
|
|
mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
|
|
mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
|
|
mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
|
|
nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
|
|
ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
|
|
neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
|
|
noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
|
|
noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
|
|
obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
|
|
openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
|
|
opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
|
|
pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
|
|
pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
|
|
plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
|
|
qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
|
|
qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
|
|
qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
|
|
qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
|
|
rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
|
|
rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
|
|
sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
|
|
simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
|
|
simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
|
|
steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
|
|
surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
|
|
terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
|
|
termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
|
|
thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
|
|
thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
|
|
tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
|
|
tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
|
|
transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
|
|
transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
|
|
transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
|
|
ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
|
|
ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
|
|
ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
|
|
ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
|
|
vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
|
|
weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
|
|
xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
|
|
xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
|
|
xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
|
|
xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
|
|
xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
|
|
zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
|
|
|
|
if [[ $UPKGS ]]; then # add any needed PKG_EXT to the list
|
|
for i in $UPKGS; do
|
|
if [[ ${PKG_EXT[$i]} ]]; then
|
|
for j in ${PKG_EXT[$i]}; do
|
|
[[ ${USER_PKGS[*]} != *"$j"* ]] && USER_PKGS+=("$j")
|
|
done
|
|
fi
|
|
done
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
###############################################################################
|
|
# partitioning menus
|
|
# non-essential partitioning helpers called by the user when using the optional
|
|
# partition menu and selecting a device to edit
|
|
|
|
part_menu()
|
|
{
|
|
is_bg_install || return 0
|
|
local device choice devhash
|
|
devhash="$(lsblk -f | base64)"
|
|
umount_dir "$MNT"
|
|
part_device || return 1
|
|
device="$DEVICE"
|
|
|
|
while :; do
|
|
choice=""
|
|
dlg choice menu "Edit Partitions" "$_part\n\n$(lsblk -no NAME,MODEL,SIZE,FSTYPE,LABEL "$device")" \
|
|
"auto" "Whole device automatic partitioning" \
|
|
"cfdisk" "Curses based variant of fdisk" \
|
|
"cgdisk" "Curses based variant of gdisk" \
|
|
"parted" "GNU partition editor" $([[ "$DISPLAY" ]] && hash gparted >/dev/null 2>&1 && printf \
|
|
"gparted 'A gui front end to parted'") \
|
|
"fdisk" "Dialog-driven creation and manipulation of partitions" \
|
|
"gdisk" "A text-mode partitioning tool that works on GUID Partition Table (GPT) disks" \
|
|
"done" "Return to the main menu"
|
|
|
|
if [[ -z $choice || $choice == 'done' ]]; then
|
|
return 0
|
|
elif [[ $choice == 'auto' ]]; then
|
|
local root_size txt label boot_fs boot_type
|
|
root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
|
|
if ($1 ~ "G") {
|
|
sub(/G/, "")
|
|
print ($1 * 1000 - 512) / 1000 "G"
|
|
} else {
|
|
sub(/M/, "")
|
|
print ($1 - 512) "M"
|
|
}}')
|
|
txt="\nWARNING: ALL data on $device will be destroyed and the following partitions will be created\n\n- "
|
|
if [[ $SYS == 'BIOS' ]]; then
|
|
label="msdos" boot_fs="ext4" boot_type="primary"
|
|
txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
|
|
else
|
|
label="gpt" boot_fs="fat32" boot_type="ESP"
|
|
txt+="A $boot_fs efi boot partition (512M)\n- "
|
|
fi
|
|
txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
|
|
yesno "Auto Partition" "$txt" && part_auto "$device" "$label" "$boot_fs" "$root_size" "$boot_type"
|
|
else
|
|
clear
|
|
tput cnorm
|
|
$choice "$device"
|
|
fi
|
|
if [[ $devhash != "$(lsblk -f | base64)" ]]; then
|
|
msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
|
|
partprobe > /dev/null 2>&1
|
|
[[ $choice == 'auto' ]] && return
|
|
fi
|
|
done
|
|
}
|
|
|
|
part_show()
|
|
{
|
|
msg "Device Tree" "\n\n$(
|
|
lsblk -no NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt/ && !'"/${IGNORE_DEV:-NONEXX}/"'{sub(/part|disk|crypt|lvm/, ""); print}'
|
|
)\n\n"
|
|
}
|
|
|
|
part_auto()
|
|
{
|
|
local device="$1" label="$2" boot_fs="$3" size="$4" boot_type="$5" dev_info=""
|
|
|
|
msg "Auto Partition" "\nRemoving partitions on $device and setting label to $label\n" 1
|
|
|
|
dev_info="$(parted -s "$device" print 2> /dev/null)"
|
|
|
|
swapoff -a
|
|
while read -r PART; do
|
|
[[ $PART ]] || continue
|
|
parted -s "$device" rm "$PART" > /dev/null 2> "$ERR"
|
|
errshow 0 "parted -s '$device' rm '$PART' > /dev/null" || return 1
|
|
done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
|
|
|
|
[[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$label" ]] && parted -s "$device" mklabel "$label" > /dev/null 2> "$ERR"
|
|
|
|
msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
|
|
parted -s "$device" mkpart "$boot_type" "$boot_fs" 1MiB 513MiB > /dev/null 2> "$ERR"
|
|
errshow 0 "parted -s '$device' mkpart '$boot_type' '$boot_fs' 1MiB 513MiB > /dev/null" || return 1
|
|
|
|
sleep 0.5
|
|
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" > /dev/null 2> "$ERR"
|
|
errshow 0 "mkfs.ext4 -q '$AUTO_BOOT' > /dev/null" || return 1
|
|
else
|
|
mkfs.vfat -F32 "$AUTO_BOOT" > /dev/null 2> "$ERR"
|
|
errshow 0 "mkfs.vfat -F32 '$AUTO_BOOT' > /dev/null" || 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% > /dev/null" || return 1
|
|
sleep 0.5
|
|
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' > /dev/null" || return 1
|
|
sleep 0.5
|
|
msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
|
|
}
|
|
|
|
###############################################################################
|
|
# partition management functions
|
|
# these are helpers used by other functions to do essential setup/teardown
|
|
|
|
part_find()
|
|
{
|
|
PARTS=""
|
|
COUNT=0
|
|
local regexp="$1" err=''
|
|
local s dev size isize model
|
|
|
|
# string of partitions >= 80M as /TYPE/PART SIZE__FSTYPE
|
|
while read -r dev size; do
|
|
[[ $dev && $size ]] || continue
|
|
s=${size%%__*}
|
|
size_t="${s: -1:1}"
|
|
isize=${s:0:-1}
|
|
isize=${isize%.*}
|
|
if [[ $dev = /dev/nvme* ]]; then
|
|
model=$(lsblk -lno MODEL "${dev%p[1-9]}")
|
|
else
|
|
model=$(lsblk -lno MODEL "${dev%[1-9]}")
|
|
fi
|
|
if ! [[ $size_t == 'K' || ($size_t == 'M' && $isize -lt 80) ]]; then
|
|
if [[ $PARTS ]]; then
|
|
PARTS+=$'\n'"$dev ${size}__$model"
|
|
else
|
|
PARTS="$dev ${size}__$model"
|
|
fi
|
|
(( COUNT++ ))
|
|
fi
|
|
done < <(lsblk -lno TYPE,PATH,SIZE,FSTYPE,LABEL |
|
|
awk "/$regexp/"' && !'"/${IGNORE_DEV:-NONEXX}/"' {
|
|
if ($4 == "") { $4 = "unformatted" }
|
|
if ($5 == "") { $5 = "unlabeled" }
|
|
print $2, $3 "__" $4 "__" $5
|
|
}')
|
|
|
|
case "$regexp" in
|
|
'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
|
|
'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
|
|
'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
|
|
esac
|
|
|
|
if [[ $err ]]; then
|
|
msg "Not Enough Partitions" "$err" 2
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
part_swap()
|
|
{
|
|
local swp="$1"
|
|
|
|
if [[ $swp == "$MNT/swapfile" && $SWAP_S ]]; then
|
|
fallocate -l $SWAP_S "$swp" 2> "$ERR"
|
|
errshow 0 "fallocate -l '$SWAP_S' '$swp'"
|
|
chmod 600 "$swp" 2> "$ERR"
|
|
errshow 0 "chmod 600 '$swp'"
|
|
fi
|
|
mkswap "$swp" > /dev/null 2> "$ERR"
|
|
errshow 0 "mkswap '$swp' > /dev/null"
|
|
swapon "$swp" > /dev/null 2> "$ERR"
|
|
errshow 0 "swapon '$swp' > /dev/null"
|
|
return 0
|
|
}
|
|
|
|
part_mount()
|
|
{
|
|
local part="$1"
|
|
local mntpt="${MNT}$2"
|
|
shift 2
|
|
local fs
|
|
fs="$(lsblk -lno FSTYPE "$part")"
|
|
|
|
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' > /dev/null" || return 1
|
|
else
|
|
mount "$part" "$mntpt" > /dev/null 2> "$ERR"
|
|
errshow 0 "mount '$part' '$mntpt' > /dev/null" || return 1
|
|
fi
|
|
|
|
msg "Mount Complete" "\nPartition $part mounted at $mntpt\n" 1
|
|
part_countdec "$part"
|
|
part_cryptlv "$part"
|
|
|
|
return 0
|
|
}
|
|
|
|
part_format()
|
|
{
|
|
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' > /dev/null" || return 1
|
|
sleep "$delay"
|
|
}
|
|
|
|
part_device()
|
|
{
|
|
if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
|
|
DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
|
|
elif (( DEV_COUNT > 1 )); then
|
|
if [[ $1 ]]; then
|
|
dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
|
|
else
|
|
dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
|
|
fi
|
|
[[ $DEVICE ]] || return 1
|
|
elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
|
|
msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
|
|
[[ $1 ]] && BOOT_D="$DEVICE"
|
|
|
|
return 0
|
|
}
|
|
|
|
part_bootdev()
|
|
{
|
|
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_D set $BOOT_NUM esp on > /dev/null 2>&1
|
|
else
|
|
parted -s $BOOT_D set $BOOT_NUM boot on > /dev/null 2>&1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
part_cryptlv()
|
|
{
|
|
local part="$1" devs=""
|
|
devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
|
|
|
|
# Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
|
|
if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
|
|
LUKS='encrypted'
|
|
LUKS_NAME="${part#/dev/mapper/}"
|
|
for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
|
|
if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
|
|
LUKS_DEV="${LUKS_DEV}cryptdevice=$dev:$LUKS_NAME "
|
|
LVM='logical volume'
|
|
break
|
|
fi
|
|
done
|
|
for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
|
|
if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; 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 "
|
|
break
|
|
fi
|
|
done
|
|
elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
|
|
LVM='logical volume'
|
|
VNAME="${part#/dev/mapper/}"
|
|
for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
|
|
if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
|
|
LUKS_NAME="${dev/\/dev\/mapper\//}"
|
|
break
|
|
fi
|
|
done
|
|
for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
|
|
if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; 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'
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
part_countdec()
|
|
{
|
|
for pt; do
|
|
if (( COUNT )); then
|
|
PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
|
|
(( COUNT-- ))
|
|
fi
|
|
done
|
|
}
|
|
|
|
###############################################################################
|
|
# mounting menus
|
|
# mount_menu is the entry point which calls all other functions
|
|
# once finished it returns to the main menu: main()
|
|
|
|
mount_menu()
|
|
{
|
|
msg "Mount Menu" "\nGathering device and partition information.\n" 1
|
|
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 || { 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 || return 1
|
|
install_background
|
|
return 0
|
|
}
|
|
|
|
select_boot()
|
|
{
|
|
local s 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
|
|
s=${size%%__*}
|
|
size_t="${s: -1:1}"
|
|
isize=${s:0:-1}
|
|
isize=${isize%.*}
|
|
if ! [[ $size_t == 'T' || ($size_t == 'G' && $isize -gt 2) ]]; then
|
|
pts+="$dev $size "
|
|
(( ptcount++ ))
|
|
fi
|
|
done <<< "$PARTS"
|
|
fi
|
|
|
|
local txt="\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n"
|
|
|
|
case "$SYS" in
|
|
UEFI)
|
|
case "$ptcount" in
|
|
0)
|
|
msg "EFI Boot Partition" "$txt" 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)
|
|
txt="\nLUKS without LVM requires a separate boot partition.$txt"
|
|
msg "Boot Partition" "$txt" 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
|
|
if [[ -z $BOOT || $BOOT == "skip" ]]; then
|
|
BOOT=''
|
|
return 0
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
local fs
|
|
fs="$(fsck -N "$BOOT")"
|
|
if ([[ $SYS == 'BIOS' ]] && grep -q 'ext[34]' <<< "$fs") || ([[ $SYS == 'UEFI' ]] && grep -q 'fat' <<< "$fs"); then
|
|
yesno "Format Boot Partition" "\nIMPORTANT: The 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 < 8G
|
|
while read -r dev size; do
|
|
s=${size%%__*}
|
|
size_t="${s: -1:1}"
|
|
isize=${s:0:-1}
|
|
isize=${isize%.*}
|
|
if ! [[ $size_t == 'M' || ($size_t == 'G' && $isize -lt 8) ]]; then
|
|
pts+="$dev $size "
|
|
(( ptcount++ ))
|
|
fi
|
|
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."
|
|
txt+="\n\nDevices smaller than 8G 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
|
|
|
|
if (( COUNT )) ; then
|
|
while read -r dev size; do # walk partition list and skip ones that are > 64G
|
|
s=${size%%__*}
|
|
size_t="${s: -1:1}"
|
|
isize=${s:0:-1}
|
|
isize=${isize%.*}
|
|
if ! [[ $size_t == 'T' || ($size_t == 'G' && $isize -gt 64) ]]; then
|
|
pts+="$dev $size "
|
|
fi
|
|
done <<< "$PARTS"
|
|
fi
|
|
|
|
dlg SWAP menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
|
|
"none" "No swap space" \
|
|
"swapfile" "/swapfile (editable size)" \
|
|
$pts
|
|
|
|
if [[ -z $SWAP || $SWAP == "none" ]]; then
|
|
SWAP=''
|
|
return 0
|
|
elif [[ $SWAP == "swapfile" ]]; then
|
|
local i=0
|
|
until [[ ${SWAP_S:0:1} =~ [1-9] && ${SWAP_S: -1} =~ (M|G) ]]; do
|
|
if (( i > 0 )); then
|
|
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
|
|
fi
|
|
if ! dlg SWAP_S input "Swap Setup" "$_swapsize" "$SYS_MEM"; then
|
|
SWAP=''
|
|
SWAP_S=''
|
|
return 1
|
|
fi
|
|
(( i++ ))
|
|
done
|
|
part_swap "$MNT/$SWAP"
|
|
SWAP="/$SWAP"
|
|
else
|
|
part_swap "$SWAP"
|
|
part_countdec "$SWAP"
|
|
SWAP_S="$(lsblk -lno SIZE $SWAP)"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
select_extra()
|
|
{
|
|
local part dev size
|
|
|
|
# walk partition list and skip ones that are < 1G
|
|
if (( COUNT )); then
|
|
while read -r dev size; do
|
|
s=${size%%__*}
|
|
[[ ${s: -1:1} == 'M' ]] && part_countdec "$dev"
|
|
done <<< "$PARTS"
|
|
fi
|
|
|
|
while (( COUNT )); do
|
|
part=''
|
|
dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
|
|
if [[ $part == 'done' ]]; then
|
|
break
|
|
elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
|
|
EXMNTS+="$part: $EXMNT "
|
|
[[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS+=" usr"
|
|
else
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
if (( COUNT == 0 )); then
|
|
msg "Mount Extra" "\nMounting Finished\n\nNo more partitions to mount, returning to main menu.\n" 2
|
|
fi
|
|
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
|
|
|
|
yesno "$title" "\nPerform automatic mount with default options?\n" "Automatic" "Custom" && return 1
|
|
until [[ $MNT_OPTS ]]; do
|
|
dlg MNT_OPTS check "$title" "$_mount" $opts
|
|
[[ $MNT_OPTS ]] || return 1 # no options is auto mount
|
|
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
|
|
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
|
|
# complete it shows a dialog to edit files on the new system before reboot
|
|
|
|
install_main()
|
|
{
|
|
install_base
|
|
genfstab -U "$MNT" > "$MNT/etc/fstab" 2> "$ERR"
|
|
errshow 1 "genfstab -U '$MNT' > '$MNT/etc/fstab'"
|
|
[[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" "$MNT/etc/fstab"
|
|
install_packages
|
|
install_tearfree "$MNT/etc/X11/xorg.conf.d"
|
|
install_mkinitcpio
|
|
install_bootldr
|
|
chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
|
|
install_user
|
|
install_login
|
|
chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
|
|
if [[ "$USER_CMD" ]]; then
|
|
chrun "$USER_CMD" 2> "$ERR" 2>&1
|
|
errshow 0 "chrun '$USER_CMD'"
|
|
fi
|
|
|
|
while :; do
|
|
dlg choice menu "Finalization" "$_edit" \
|
|
finished "exit the installer and reboot" \
|
|
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]}"
|
|
|
|
if [[ -z $choice || $choice == 'finished' ]]; then
|
|
[[ $DEBUG == true && -r $DBG ]] && ${EDITOR:-vim} "$DBG"
|
|
clear
|
|
die 127
|
|
else
|
|
for f in ${EDIT_FILES[$choice]}; do
|
|
if [[ -e ${MNT}$f ]]; then
|
|
${EDITOR:-vim} "${MNT}$f"
|
|
else
|
|
msg "File Missing" "\nThe file(s) selected do not exist:\n\n${MNT}$f\n"
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
}
|
|
|
|
install_base()
|
|
{
|
|
clear
|
|
tput cnorm
|
|
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
|
|
|
|
if [[ $PACSTRAP == 1 ]]; then
|
|
# we have some customizations in /etc on the iso we want to preserve
|
|
if [[ $DIST == "ArchLabs" ]]; then
|
|
cp -vf /etc/dialogrc "$MNT/etc/dialogrc"
|
|
cp -vf /etc/os-release "$MNT/etc/os-release"
|
|
cp -vf /etc/lsb-release "$MNT/etc/lsb-release"
|
|
cp -vf /etc/skel/.zshrc "$MNT/etc/skel/.zshrc"
|
|
cp -vf /etc/pacman.conf "$MNT/etc/pacman.conf"
|
|
cp -vf /etc/modprobe.d/* "$MNT/etc/modprobe.d/"
|
|
cp -vf /etc/X11/xorg.conf.d/* "$MNT/etc/X11/xorg.conf.d/"
|
|
fi
|
|
else
|
|
# archiso files
|
|
rm -rf "$MNT/etc/mkinitcpio-archiso.conf"
|
|
find "$MNT/usr/lib/initcpio" -name 'archiso*' -type f -delete
|
|
|
|
# vmlinuz, if this isn't copied the standard kernel may fail mkinitcpio
|
|
cp -vf "$RUN/x86_64/vmlinuz" "$MNT/boot/vmlinuz-linux" 2> "$ERR"
|
|
errshow 1 "cp -vf '$RUN/x86_64/vmlinuz' '$MNT/boot/vmlinuz-linux'"
|
|
|
|
# remove/disable customizations done to airootfs during building
|
|
chrun "systemctl disable pacman-init.service choose-mirror.service" > /dev/null 2>&1
|
|
rm -f "$MNT/etc/systemd/scripts/choose-mirror"
|
|
rm -f "$MNT/etc/systemd/system/"{choose-mirror.service,etc-pacman.d-gnupg.mount,pacman-init.service}
|
|
sed -i 's/#\(Storage=\)volatile/\1auto/' "$MNT/etc/systemd/journald.conf"
|
|
sed -i 's/\(HandleLidSwitch=\)ignore/#\1suspend/' "$MNT/etc/systemd/logind.conf"
|
|
sed -i 's/\(HandleSuspendKey=\)ignore/#\1suspend/' "$MNT/etc/systemd/logind.conf"
|
|
sed -i 's/\(HandleHibernateKey=\)ignore/#\1hibernate/' "$MNT/etc/systemd/logind.conf"
|
|
find "$MNT/boot" -name '*-ucode.img' -delete
|
|
fi
|
|
|
|
# changing distro name?
|
|
[[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" "$MNT/etc/"{lsb-release,os-release}
|
|
|
|
# copy network settings
|
|
[[ -d /etc/netctl ]] && cp -rfv /etc/netctl "$MNT/etc/"
|
|
[[ -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/"
|
|
|
|
mkdir -pv "$MNT/etc/default"
|
|
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/#${LOCALE}/${LOCALE}/g" "$MNT/etc/locale.gen"
|
|
chrun "locale-gen"
|
|
chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
|
|
|
|
mkdir -pv "$MNT/etc/X11/xorg.conf.d"
|
|
cat > "$MNT/etc/X11/xorg.conf.d/00-keyboard.conf" <<- EOF
|
|
# Use localectl(1) to instruct systemd-localed to update it.
|
|
Section "InputClass"
|
|
Identifier "system-keyboard"
|
|
MatchIsKeyboard "on"
|
|
Option "XkbLayout" "$KEYMAP"
|
|
EndSection
|
|
EOF
|
|
|
|
cat > "$MNT/etc/default/keyboard" <<- EOF
|
|
# KEYBOARD CONFIGURATION FILE
|
|
# Consult the keyboard(5) manual page.
|
|
XKBMODEL=""
|
|
XKBLAYOUT="$KEYMAP"
|
|
XKBVARIANT=""
|
|
XKBOPTIONS=""
|
|
BACKSPACE="guess"
|
|
EOF
|
|
printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > "$MNT/etc/vconsole.conf"
|
|
|
|
echo "$NEWHOST" > "$MNT/etc/hostname"
|
|
cat > "$MNT/etc/hosts" <<- EOF
|
|
127.0.0.1 localhost
|
|
127.0.1.1 $NEWHOST
|
|
::1 localhost ip6-localhost ip6-loopback
|
|
ff02::1 ip6-allnodes
|
|
ff02::2 ip6-allrouters
|
|
EOF
|
|
}
|
|
|
|
install_user()
|
|
{
|
|
local groups='audio,video,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
|
|
[[ -e $MNT/etc/X11/xorg.conf.d/20-nvida.conf && -e $MNT/usr/bin/optirun ]] && groups+=',bumblebee'
|
|
|
|
rm -f "$MNT/root/.zlogin" # remove welcome message
|
|
|
|
chrun "chpasswd <<< 'root:$ROOT_PASS'" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'chpasswd <<< \"root:$ROOT_PASS\"'"
|
|
if [[ $NEWSHELL != 'zsh' ]]; then # root uses zsh by default
|
|
chrun "usermod -s /bin/$NEWSHELL root" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'usermod -s /bin/$NEWSHELL root'"
|
|
# copy the default mkshrc to /root if it was selected
|
|
[[ $NEWSHELL == 'mksh' ]] && cp -fv "$MNT/etc/skel/.mkshrc" "$MNT/root/.mkshrc"
|
|
fi
|
|
|
|
echo "Creating new user $NEWUSER and setting password"
|
|
chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$NEWSHELL $NEWUSER" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'useradd -m -u 1000 -g users -G $groups -s /bin/$NEWSHELL $NEWUSER'"
|
|
chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'chpasswd <<< \"$NEWUSER:$USER_PASS\"'"
|
|
|
|
[[ $INSTALL_WMS == *dwm* ]] && install_suckless "/home/$NEWUSER" chroot
|
|
|
|
install_cleanup "$NEWUSER"
|
|
|
|
return 0
|
|
}
|
|
|
|
install_login()
|
|
{
|
|
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"
|
|
errshow 1 "chrun 'systemctl enable $LOGIN_TYPE.service'"
|
|
fi
|
|
|
|
config_${LOGIN_TYPE}
|
|
}
|
|
|
|
install_cleanup()
|
|
{
|
|
local user="$1"
|
|
|
|
# remove tint2 configs if bspwm and openbox aren't being installed
|
|
[[ $INSTALL_WMS =~ (bspwm|openbox) ]] || rm -rf "$MNT/home/$user/.config/tint2"
|
|
|
|
# remove jgmenu configs if bspwm, fluxbox, and openbox aren't being installed
|
|
[[ $INSTALL_WMS =~ (fluxbox|bspwm|openbox) ]] || rm -rf "$MNT/home/$user/.config/jgmenu"
|
|
|
|
# remove geany configs if it wasn't installed
|
|
[[ ${USER_PKGS[*]} != *geany* ]] && rm -rf "$MNT/home/$user/.config/geany"
|
|
|
|
# remove shell stuff for unused shells
|
|
[[ $NEWSHELL != 'bash' ]] && rm -rf "$MNT/home/$user/.bash"*
|
|
[[ $NEWSHELL != '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 login
|
|
[[ $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
|
|
|
|
}
|
|
|
|
install_bootldr()
|
|
{
|
|
local uuid_type="UUID"
|
|
|
|
echo "Installing $BOOTLDR"
|
|
|
|
if [[ $ROOT == /dev/mapper* ]]; then
|
|
ROOT_ID="$ROOT"
|
|
else
|
|
[[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
|
|
ROOT_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT)"
|
|
fi
|
|
|
|
if [[ $SYS == 'UEFI' ]]; then
|
|
# remove our old install and generic BOOT/ dir
|
|
echo "Removing conflicting boot directories"
|
|
find "$MNT/boot/EFI/" -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete -printf "remove %p\n"
|
|
find "$MNT/boot/EFI/" -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete -printf "remove %p\n"
|
|
fi
|
|
|
|
if [[ $SWAP ]]; then # attempt to setup swap space for suspend/resume
|
|
if [[ $SWAP == /dev/mapper* ]]; then
|
|
RESUME="resume=$SWAP "
|
|
elif [[ $SWAP == "/swapfile" ]]; then
|
|
RESUME="resume=$ROOT_ID resume_offset=$(filefrag -v "${MNT}$SWAP" | awk '{ if ($1=="0:") { gsub(/\./, ""); print $4 } }') "
|
|
else
|
|
RESUME="resume=$uuid_type=$(blkid -s $uuid_type -o value "$SWAP") "
|
|
fi
|
|
fi
|
|
|
|
prerun_$BOOTLDR
|
|
chrun "${BCMDS[$BOOTLDR]}" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun '${BCMDS[$BOOTLDR]}'"
|
|
|
|
if [[ -d $MNT/hostrun ]]; then
|
|
echo "Unmounting chroot directories"
|
|
# cleanup the bind mounts we made earlier for the grub-probe module
|
|
umount_dir "$MNT/hostrun/"{udev,lvm}
|
|
rm -rf "$MNT/hostrun" > /dev/null 2>&1
|
|
fi
|
|
|
|
if [[ $SYS == 'UEFI' ]]; then
|
|
# some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
|
|
mkdir -pv "$MNT/boot/EFI/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"
|
|
cp -fv "$MNT/boot/EFI/refind/refind_x64.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;;
|
|
esac
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
install_packages()
|
|
{
|
|
typeset -a inpkg rmpkg loginpkg
|
|
|
|
for i in "${PACKAGES[@]}"; do
|
|
inpkg+=("$i")
|
|
done
|
|
for i in "${USER_PKGS[@]}"; do
|
|
inpkg+=("$i")
|
|
done
|
|
for i in "${AL_PKGS[@]}"; do
|
|
inpkg+=("$i")
|
|
done
|
|
for i in ${LOGIN_PKGS[$LOGIN_TYPE]}; do
|
|
loginpkg+=("$i")
|
|
done
|
|
|
|
if [[ $INSTALL_WMS =~ ($WM_PKG_SES) ]]; then
|
|
for i in "${WM_PKGS[@]}"; do
|
|
inpkg+=("$i")
|
|
done
|
|
fi
|
|
|
|
if [[ $NEWSHELL == 'zsh' ]]; then
|
|
inpkg+=("zsh-completions")
|
|
elif [[ $PACSTRAP != 1 ]]; then
|
|
rmpkg+=("archlabs-installer" "zsh")
|
|
fi
|
|
|
|
# update and install crucial packages first to avoid issues
|
|
chrun "pacman -Syyu --noconfirm" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -Syyu --noconfirm'"
|
|
chrun "pacman -S ${BASE_PKGS[*]} ${loginpkg[*]} $NEWSHELL --noconfirm --needed" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S ${BASE_PKGS[*]} ${loginpkg[*]} $NEWSHELL --noconfirm --needed'"
|
|
if [[ $PACSTRAP == 1 ]]; then
|
|
chrun "pacman -S ${ISO_PKGS[*]} --noconfirm --needed" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S ${ISO_PKGS[*]} --noconfirm --needed'"
|
|
fi
|
|
|
|
# reinstalling iputils fixes the network issue for non-root users
|
|
chrun "pacman -S iputils $UCODE $KERNEL --noconfirm"
|
|
|
|
# remove the packages we don't want on the installed system
|
|
[[ ${rmpkg[*]} ]] && chrun "pacman -Rnsc ${rmpkg[*]} --noconfirm"
|
|
|
|
# install the packages chosen throughout the install
|
|
chrun "pacman -S ${inpkg[*]} --needed --noconfirm" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S ${inpkg[*]} --needed --noconfirm'"
|
|
|
|
# bootloader packages
|
|
if [[ $BOOTLDR == 'grub' ]]; then
|
|
[[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
|
|
chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S os-prober grub $efib --needed --noconfirm'"
|
|
elif [[ $BOOTLDR == 'refind-efi' ]]; then
|
|
chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S refind-efi efibootmgr --needed --noconfirm'"
|
|
elif [[ $SYS == 'UEFI' ]]; then
|
|
chrun "pacman -S efibootmgr --needed --noconfirm" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'pacman -S efibootmgr --needed --noconfirm'"
|
|
fi
|
|
|
|
if [[ $VM ]] && dmesg | grep -qi 'vbox'; then
|
|
case "$KERNEL" in
|
|
linux) chrun "pacman -S virtualbox-guest-utils virtualbox-guest-modules-arch --needed --noconfirm" ;;
|
|
*) chrun "pacman -S virtualbox-guest-utils virtualbox-guest-modules-dkms ${KERNEL}-headers --needed --noconfirm" ;;
|
|
esac
|
|
fi
|
|
|
|
# allow members of the wheel group to run commands as root
|
|
sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" "$MNT/etc/sudoers"
|
|
|
|
return 0
|
|
}
|
|
|
|
install_suckless()
|
|
{
|
|
local dir="$1/suckless"
|
|
shift
|
|
|
|
if [[ $1 == 'chroot' ]]; then
|
|
chrun "mkdir -pv '$dir'"
|
|
for i in dwm dmenu st; do
|
|
if chrun "git clone 'https://git.suckless.org/$i' '$dir/$i'"; then
|
|
chrun "cd '$dir/$i' && make PREFIX=/usr install"
|
|
else
|
|
printf "failed to clone %s repo\n" "$i"
|
|
fi
|
|
done
|
|
else
|
|
mkdir -pv "$dir"
|
|
for i in dwm dmenu st; do
|
|
if git clone "https://git.suckless.org/$i" "$dir/$i"; then
|
|
cd "$dir/$i" && make PREFIX=/usr install
|
|
else
|
|
printf "failed to clone %s repo\n" "$i"
|
|
fi
|
|
done
|
|
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-nvidia.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
|
|
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
|
|
|
|
if [[ $PACSTRAP != 1 ]]; then
|
|
# remove nvidia installer from installed system
|
|
[[ $xpath == *"$MNT"* ]] && rm -rf "$MNT/usr/bin/nvidia-installer" "$MNT/var/lib/nvidia-installer"
|
|
fi
|
|
}
|
|
|
|
install_mkinitcpio()
|
|
{
|
|
local add=''
|
|
|
|
[[ $LUKS ]] && add+=" encrypt"
|
|
[[ $LVM ]] && add+=" lvm2"
|
|
[[ $SWAP ]] && add+=" resume"
|
|
sed -i "s/block filesystems/block${add} filesystems ${HOOKS}/g" "$MNT/etc/mkinitcpio.conf"
|
|
chrun "mkinitcpio -p $KERNEL" 2> "$ERR" 2>&1
|
|
errshow 1 "chrun 'mkinitcpio -p $KERNEL'"
|
|
}
|
|
|
|
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... 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'])")"
|
|
|
|
if [[ "$country" ]]; then
|
|
if [[ $country =~ (CA|US) ]]; then
|
|
# use both CA and US mirrors for CA or US countries
|
|
mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
|
|
elif [[ $country =~ (AU|NZ) ]]; then
|
|
# use both AU and NZ mirrors for AU or NZ countries
|
|
mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
|
|
else
|
|
mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
|
|
fi
|
|
else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
|
|
mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
|
|
fi
|
|
curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - > "$1"
|
|
fi
|
|
}
|
|
|
|
install_background()
|
|
{
|
|
if yesno "Base Install" "$_bginstall" "Pacstrap" "Copy iso"; then
|
|
PACSTRAP=1
|
|
(
|
|
install_mirrorlist "/etc/pacman.d/mirrorlist" > /tmp/bgout 2>&1 &&
|
|
pacstrap /mnt ${BASE_PKGS[*]} > /tmp/bgout 2>&1 &&
|
|
cp /etc/pacman.d/mirrorlist "$MNT/etc/pacman.d/mirrorlist"
|
|
cp /etc/pacman.conf "$MNT/etc/pacman.conf"
|
|
al_repo "$MNT/etc/pacman.conf"
|
|
chrun "systemctl enable NetworkManager.service" > /tmp/bgout 2>&1
|
|
) &
|
|
BG_PID=$!
|
|
else
|
|
PACSTRAP=0
|
|
(
|
|
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 -Sy && pacman -Syyu ${BASE_PKGS[*]} --noconfirm --needed" > /tmp/bgout 2>&1
|
|
) &
|
|
BG_PID=$!
|
|
fi
|
|
# shellcheck disable=SC2064
|
|
trap "kill $BG_PID 2> /dev/null" EXIT
|
|
}
|
|
|
|
###############################################################################
|
|
# 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 and xinit.
|
|
|
|
config_ly()
|
|
{
|
|
: #TODO
|
|
}
|
|
|
|
config_gdm()
|
|
{
|
|
: #TODO
|
|
}
|
|
|
|
config_sddm()
|
|
{
|
|
: #TODO
|
|
}
|
|
|
|
config_xinit()
|
|
{
|
|
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
|
|
else
|
|
rm -rf "$AUTOLOGIN_SERV"
|
|
fi
|
|
|
|
# run `startx` after logging in regardless of autologin
|
|
cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
|
|
# automatically run startx when logging in on tty1
|
|
[ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ] && startx
|
|
EOF
|
|
}
|
|
|
|
config_lightdm()
|
|
{
|
|
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
|
|
}
|
|
|
|
###############################################################################
|
|
# bootloader setup
|
|
# prerun_* set up the configs needed before actually running the commands
|
|
# setup_* are run after selecting a bootloader and build the command used later
|
|
# they can also be used for further user input as these run before control is taken away
|
|
|
|
setup_grub()
|
|
{
|
|
EDIT_FILES[bootloader]="/etc/default/grub"
|
|
|
|
if [[ $SYS == 'BIOS' ]]; then
|
|
[[ $BOOT_D ]] || { part_device 1 || return 1; }
|
|
BCMDS[grub]="grub-install --verbose --recheck --force --target=i386-pc $BOOT_D"
|
|
else
|
|
BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
|
|
grub-install --verbose --recheck --force --target=x86_64-efi --efi-directory=/boot --bootloader-id='$DIST'"
|
|
grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
|
|
fi
|
|
|
|
BCMDS[grub]="mkdir -p /run/udev /run/lvm && mount --bind /hostrun/udev /run/udev && mount --bind /hostrun/lvm /run/lvm &&
|
|
${BCMDS[grub]} && grub-mkconfig -o /boot/grub/grub.cfg && sleep 1 && umount /run/udev /run/lvm"
|
|
|
|
return 0
|
|
}
|
|
|
|
prerun_grub()
|
|
{
|
|
sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" "$MNT/etc/default/grub"
|
|
if [[ $LUKS_DEV ]]; then
|
|
sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" "$MNT/etc/default/grub"
|
|
fi
|
|
if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
|
|
sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" "$MNT/etc/default/grub"
|
|
fi
|
|
# setup for os-prober module
|
|
mkdir -p /run/{lvm,udev} "$MNT/hostrun/"{lvm,udev}
|
|
mount --bind /run/lvm "$MNT/hostrun/lvm"
|
|
mount --bind /run/udev "$MNT/hostrun/udev"
|
|
|
|
return 0
|
|
}
|
|
|
|
setup_efistub()
|
|
{
|
|
EDIT_FILES[bootloader]=""
|
|
}
|
|
|
|
prerun_efistub()
|
|
{
|
|
BCMDS[efistub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
|
|
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()
|
|
{
|
|
if [[ $SYS == 'BIOS' ]]; then
|
|
EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
|
|
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_D -p $BOOT_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
|
|
fi
|
|
}
|
|
|
|
prerun_syslinux()
|
|
{
|
|
local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios"
|
|
local d=".." # for non-UEFI systems we need to use ../path
|
|
|
|
if [[ $SYS == 'UEFI' ]]; then
|
|
c="$MNT/boot/EFI/syslinux" s="/usr/lib/syslinux/efi64" d='';
|
|
fi
|
|
|
|
mkdir -pv "$c"
|
|
cp -rfv "$s/"* "$c/"
|
|
cp -fv "$RUN/syslinux/splash.png" "$c/"
|
|
|
|
cat > "$c/syslinux.cfg" <<- EOF
|
|
UI vesamenu.c32
|
|
MENU TITLE $DIST Boot Menu
|
|
MENU BACKGROUND splash.png
|
|
TIMEOUT 50
|
|
DEFAULT $DIST
|
|
|
|
# see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
|
|
MENU WIDTH 78
|
|
MENU MARGIN 4
|
|
MENU ROWS 4
|
|
MENU VSHIFT 10
|
|
MENU TIMEOUTROW 13
|
|
MENU TABMSGROW 14
|
|
MENU CMDLINEROW 14
|
|
MENU HELPMSGROW 16
|
|
MENU HELPMSGENDROW 29
|
|
MENU COLOR border 30;44 #40ffffff #a0000000 std
|
|
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
|
|
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
|
|
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
|
|
MENU COLOR help 37;40 #c0ffffff #a0000000 std
|
|
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
|
|
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
|
|
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
|
|
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
|
|
|
|
LABEL $DIST
|
|
MENU LABEL $DIST Linux
|
|
LINUX $d/vmlinuz-$KERNEL
|
|
APPEND root=$ROOT_ID ${LUKS_DEV}${RESUME}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_ID ${LUKS_DEV}${RESUME}rw
|
|
INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
|
|
EOF
|
|
return 0
|
|
}
|
|
|
|
setup_refind-efi()
|
|
{
|
|
EDIT_FILES[bootloader]="/boot/refind_linux.conf"
|
|
BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1; refind-install"
|
|
}
|
|
|
|
prerun_refind-efi()
|
|
{
|
|
cat > "$MNT/boot/refind_linux.conf" <<- EOF
|
|
"$DIST Linux" "root=$ROOT_ID ${LUKS_DEV}${RESUME}rw add_efi_memmap $([[ $UCODE ]] &&
|
|
printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-%v.img"
|
|
"$DIST Linux Fallback" "root=$ROOT_ID ${LUKS_DEV}${RESUME}rw add_efi_memmap $([[ $UCODE ]] &&
|
|
printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-%v-fallback.img"
|
|
EOF
|
|
|
|
mkdir -p "$MNT/etc/pacman.d/hooks"
|
|
|
|
cat > "$MNT/etc/pacman.d/hooks/refind.hook" <<- EOF
|
|
[Trigger]
|
|
Operation = Upgrade
|
|
Type = Package
|
|
Target = refind-efi
|
|
|
|
[Action]
|
|
Description = Updating rEFInd on ESP
|
|
When = PostTransaction
|
|
Exec = /usr/bin/refind-install
|
|
EOF
|
|
}
|
|
|
|
setup_systemd-boot()
|
|
{
|
|
EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
|
|
BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1; systemd-machine-id-setup && bootctl --path=/boot install"
|
|
}
|
|
|
|
prerun_systemd-boot()
|
|
{
|
|
mkdir -pv "$MNT/boot/loader/entries"
|
|
|
|
cat > "$MNT/boot/loader/loader.conf" <<- EOF
|
|
default $DIST
|
|
timeout 5
|
|
editor no
|
|
EOF
|
|
|
|
cat > "$MNT/boot/loader/entries/$DIST.conf" <<- EOF
|
|
title $DIST Linux
|
|
linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
|
|
initrd /initramfs-$KERNEL.img
|
|
options root=$ROOT_ID ${LUKS_DEV}${RESUME}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_ID ${LUKS_DEV}${RESUME}rw
|
|
EOF
|
|
|
|
mkdir -pv "$MNT/etc/pacman.d/hooks"
|
|
|
|
cat > "$MNT/etc/pacman.d/hooks/systemd-boot.hook" <<- EOF
|
|
[Trigger]
|
|
Type = Package
|
|
Operation = Upgrade
|
|
Target = systemd
|
|
|
|
[Action]
|
|
Description = Updating systemd-boot
|
|
When = PostTransaction
|
|
Exec = /usr/bin/bootctl update
|
|
EOF
|
|
return 0
|
|
}
|
|
|
|
###############################################################################
|
|
# lvm functions
|
|
|
|
lvm_menu()
|
|
{
|
|
is_bg_install || return 1
|
|
lvm_detect
|
|
local choice
|
|
while :; do
|
|
dlg choice menu "Logical Volume Management" "$_lvmmenu" \
|
|
"$_lvmnew" "vgcreate -f, lvcreate -L -n" \
|
|
"$_lvmdel" "vgremove -f" \
|
|
"$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
|
|
"Back" "Return to the main menu"
|
|
case "$choice" in
|
|
"$_lvmnew") lvm_create && break ;;
|
|
"$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" > /dev/null 2>&1 ;;
|
|
"$_lvmdelall") lvm_del_all ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
lvm_detect()
|
|
{
|
|
if [[ $(vgs -o vg_name --noheading 2> /dev/null) ]]; then
|
|
if [[ $(lvs -o vg_name,lv_name --noheading --separator - 2> /dev/null) && $(pvs -o pv_name --noheading 2> /dev/null) ]]; then
|
|
msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
|
|
modprobe dm-mod > /dev/null 2> "$ERR"
|
|
errshow 0 'modprobe dm-mod > /dev/null'
|
|
vgscan > /dev/null 2>&1
|
|
vgchange -ay > /dev/null 2>&1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
lvm_create()
|
|
{
|
|
VGROUP='' LVM_PARTS='' VGROUP_MB=0
|
|
umount_dir "$MNT"
|
|
lvm_mkgroup || return 1
|
|
local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
|
|
dlg VOL_COUNT menu "$_lvmnew" "\nSelect the number of logical volumes (LVs) to create in: $VGROUP\n$txt" 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -
|
|
[[ $VOL_COUNT ]] || return 1
|
|
lvm_extra_lvs || return 1
|
|
lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
|
|
msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
|
|
lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" > /dev/null 2> "$ERR"
|
|
errshow 0 "lvcreate -l +100%FREE '$VGROUP' -n '$VNAME' >/dev/null" || return 1
|
|
LVM='logical volume'; sleep 0.5
|
|
txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
|
|
msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,SIZE $LVM_PARTS)\n"
|
|
return 0
|
|
}
|
|
|
|
lvm_lv_size()
|
|
{
|
|
local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
|
|
|
|
while :; do
|
|
ERR_SIZE=0
|
|
dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
|
|
if [[ -z $VOLUME_SIZE ]]; then
|
|
ERR_SIZE=1
|
|
break # allow bailing with escape or an empty choice
|
|
elif (( ${VOLUME_SIZE:0:1} == 0 )); then
|
|
ERR_SIZE=1 # size values can't begin with '0'
|
|
else
|
|
# walk the string and make sure all but the last char are digits
|
|
local lv=$((${#VOLUME_SIZE} - 1))
|
|
for (( i=0; i<lv; i++ )); do
|
|
[[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
|
|
done
|
|
if (( ERR_SIZE != 1 )); then
|
|
case ${VOLUME_SIZE:$lv:1} in
|
|
[mMgG])
|
|
local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
|
|
case ${VOLUME_SIZE:$lv:1} in
|
|
[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
|
|
;;
|
|
*) ERR_SIZE=1
|
|
esac
|
|
fi
|
|
fi
|
|
(( ERR_SIZE )) || break
|
|
msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
|
|
done
|
|
|
|
return $ERR_SIZE
|
|
}
|
|
|
|
lvm_mkgroup()
|
|
{
|
|
local named=''
|
|
|
|
until [[ $named ]]; do
|
|
lvm_partitions || return 1
|
|
lvm_group_name || return 1
|
|
yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
|
|
done
|
|
|
|
msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
|
|
vgcreate -f "$VGROUP" $LVM_PARTS > /dev/null 2> "$ERR"
|
|
errshow 0 "vgcreate -f '$VGROUP' $LVM_PARTS >/dev/null" || return 1
|
|
|
|
SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
|
|
SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
|
|
|
|
if [[ $SIZE_UNIT == 'G' ]]; then
|
|
VGROUP_MB=$((SIZE * 1000))
|
|
else
|
|
VGROUP_MB=$SIZE
|
|
fi
|
|
|
|
msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
|
|
}
|
|
|
|
lvm_del_all()
|
|
{
|
|
local v pv
|
|
pv="$(pvs -o pv_name --noheading 2> /dev/null)"
|
|
v="$(lvs -o vg_name,lv_name --noheading --separator - 2> /dev/null)"
|
|
VGROUP="$(vgs -o vg_name --noheading 2> /dev/null)"
|
|
|
|
if [[ $VGROUP || $v || $pv ]]; then
|
|
if yesno "$_lvmdelall" "$_lvmdelask"; then
|
|
for i in $v; do lvremove -f "/dev/mapper/$i" > /dev/null 2>&1; done
|
|
for i in $VGROUP; do vgremove -f "$i" > /dev/null 2>&1; done
|
|
for i in $pv; do pvremove -f "$i" > /dev/null 2>&1; done
|
|
LVM=''
|
|
fi
|
|
else
|
|
msg "Delete LVM" "\nNo LVMs to remove...\n" 2
|
|
LVM=''
|
|
fi
|
|
}
|
|
|
|
lvm_delgroup()
|
|
{
|
|
DEL_VG=''
|
|
VOL_GROUP_LIST=''
|
|
|
|
for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
|
|
VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
|
|
done
|
|
|
|
[[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
|
|
|
|
dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
|
|
[[ $DEL_VG ]]
|
|
}
|
|
|
|
lvm_extra_lvs()
|
|
{
|
|
while (( VOL_COUNT > 1 )); do
|
|
lvm_volume_name "$_lvmlvname" || return 1
|
|
lvm_lv_size || return 1
|
|
msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
|
|
lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" > /dev/null 2> "$ERR"
|
|
errshow 0 "lvcreate -L '$VOLUME_SIZE' '$VGROUP' -n '$VNAME'" || return 1
|
|
msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
|
|
(( VOL_COUNT-- ))
|
|
done
|
|
return 0
|
|
}
|
|
|
|
lvm_partitions()
|
|
{
|
|
part_find 'part|crypt' || return 1
|
|
PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
|
|
dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
|
|
}
|
|
|
|
lvm_group_name()
|
|
{
|
|
VGROUP=''
|
|
until [[ $VGROUP ]]; do
|
|
dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
|
|
if [[ -z $VGROUP ]]; then
|
|
return 1
|
|
elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
|
|
msg "LVM Name Error" "$_lvmerrvgname"
|
|
VGROUP=''
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
lvm_volume_name()
|
|
{
|
|
VNAME=''
|
|
local txt="$1" default="mainvolume"
|
|
(( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
|
|
until [[ $VNAME ]]; do
|
|
dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
|
|
if [[ -z $VNAME ]]; then
|
|
return 1
|
|
elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
|
|
msg "LVM Name Error" "$_lvmerlvname"
|
|
VNAME=''
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
###############################################################################
|
|
# luks functions
|
|
|
|
luks_menu()
|
|
{
|
|
local choice
|
|
is_bg_install || return 1
|
|
dlg choice menu "LUKS Encryption" "$_luksmenu" \
|
|
"$_luksnew" "cryptsetup -q luksFormat" \
|
|
"$_luksopen" "cryptsetup open --type luks" \
|
|
"$_luksadv" "cryptsetup -q -s -c luksFormat" \
|
|
"Back" "Return to the main menu"
|
|
|
|
case "$choice" in
|
|
"$_luksnew") luks_basic || return 1 ;;
|
|
"$_luksopen") luks_open || return 1 ;;
|
|
"$_luksadv") luks_advanced || return 1 ;;
|
|
esac
|
|
|
|
return 0
|
|
}
|
|
|
|
luks_open()
|
|
{
|
|
modprobe -a dm-mod dm_crypt > /dev/null 2>&1
|
|
umount_dir "$MNT"
|
|
part_find 'part|crypt|lvm' || return 1
|
|
|
|
if (( COUNT == 1 )); then
|
|
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
|
|
else
|
|
dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
|
|
fi
|
|
|
|
[[ $LUKS_PART ]] || return 1
|
|
|
|
luks_pass "$_luksopen" || return 1
|
|
msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
|
|
cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
|
|
errshow 0 "cryptsetup open --type luks '$LUKS_PART' '$LUKS_NAME' <<< '$LUKS_PASS'" || return 1
|
|
LUKS='encrypted'; luks_show
|
|
return 0
|
|
}
|
|
|
|
luks_pass()
|
|
{
|
|
LUKS_PASS=''
|
|
local t="$1"
|
|
typeset -a ans=(cryptroot) # default name to start
|
|
|
|
until [[ $LUKS_PASS ]]; do
|
|
tput cnorm
|
|
dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" \
|
|
--separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
|
|
"Name:" 1 1 "${ans[0]}" 1 7 "$COLUMNS" 0 0 \
|
|
"Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
|
|
"Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2> "$ANS" || return 1
|
|
|
|
mapfile -t ans <"$ANS"
|
|
|
|
if [[ -z "${ans[0]}" ]]; then
|
|
msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
|
|
elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
|
|
LUKS_NAME="${ans[0]}"
|
|
msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
|
|
else
|
|
LUKS_NAME="${ans[0]}"
|
|
LUKS_PASS="${ans[1]}"
|
|
fi
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
luks_show()
|
|
{
|
|
sleep 0.5
|
|
msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,SIZE,FSTYPE "$LUKS_PART")\n\n"
|
|
}
|
|
|
|
luks_setup()
|
|
{
|
|
modprobe -a dm-mod dm_crypt > /dev/null 2>&1
|
|
umount_dir "$MNT"
|
|
part_find 'part|lvm' || return 1
|
|
|
|
if [[ $AUTO_ROOT ]]; then
|
|
LUKS_PART="$AUTO_ROOT"
|
|
elif (( COUNT == 1 )); then
|
|
LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
|
|
else
|
|
dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
|
|
fi
|
|
|
|
[[ $LUKS_PART ]] || return 1
|
|
luks_pass "$_luksnew"
|
|
}
|
|
|
|
luks_basic()
|
|
{
|
|
luks_setup || return 1
|
|
msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
|
|
cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2> "$ERR"
|
|
errshow 0 "cryptsetup -q luksFormat '$LUKS_PART' <<< '$LUKS_PASS'" || return 1
|
|
cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
|
|
errshow 0 "cryptsetup open '$LUKS_PART' '$LUKS_NAME' <<< '$LUKS_PASS'" || return 1
|
|
LUKS='encrypted'
|
|
luks_show
|
|
return 0
|
|
}
|
|
|
|
luks_advanced()
|
|
{
|
|
luks_setup || return 1
|
|
local cipher
|
|
dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
|
|
[[ $cipher ]] || return 1
|
|
msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
|
|
cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2> "$ERR"
|
|
errshow 0 "cryptsetup -q $cipher luksFormat '$LUKS_PART' <<< '$LUKS_PASS'" || return 1
|
|
cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
|
|
errshow 0 "cryptsetup open '$LUKS_PART' '$LUKS_NAME' <<< '$LUKS_PASS'" || return 1
|
|
LUKS='encrypted'
|
|
luks_show
|
|
return 0
|
|
}
|
|
|
|
###############################################################################
|
|
# simple functions
|
|
# some help avoid repetition and improve usability of some commands
|
|
# others are initial setup functions used before reaching the main loop
|
|
|
|
ofn()
|
|
{
|
|
[[ "$2" == *"$1"* ]] && printf "on" || printf "off"
|
|
}
|
|
|
|
die()
|
|
{
|
|
# cleanup and exit the installer cleanly with exit code $1
|
|
local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
|
|
|
|
trap - INT
|
|
tput cnorm
|
|
if [[ -d $MNT ]]; then
|
|
umount_dir "$MNT"
|
|
(( e == 127 )) && umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
|
|
fi
|
|
exit $e
|
|
}
|
|
|
|
dlg()
|
|
{
|
|
local var="$1" # assign output from dialog to var
|
|
local dlg_t="$2" # dialog type (menu, check, input)
|
|
local title="$3" # dialog title
|
|
local body="$4" # dialog message
|
|
local n=0 # number of items to display for menu and check dialogs
|
|
|
|
shift 4 # shift off args assigned above
|
|
|
|
# adjust n when passed a large list
|
|
local l=$((LINES - 20))
|
|
(( ($# / 2) > l )) && n=$l
|
|
|
|
tput civis
|
|
case "$dlg_t" in
|
|
menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2> "$ANS" || return 1 ;;
|
|
check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2> "$ANS" || return 1 ;;
|
|
input)
|
|
tput cnorm
|
|
local def="$1" # assign default value for input
|
|
shift
|
|
if [[ $1 == 'limit' ]]; then
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2> "$ANS" || return 1
|
|
else
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2> "$ANS" || return 1
|
|
fi
|
|
;;
|
|
esac
|
|
# if answer file isn't empty read from it into $var
|
|
[[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
|
|
}
|
|
|
|
msg()
|
|
{
|
|
# displays a message dialog
|
|
# when more than 2 args the message will disappear after sleep time ($3)
|
|
local title="$1"
|
|
local body="$2"
|
|
shift 2
|
|
tput civis
|
|
if (( $# )); then
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
|
|
else
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
|
|
fi
|
|
}
|
|
|
|
live()
|
|
{
|
|
local ses="$1"
|
|
|
|
if ! select_keymap; then
|
|
clear
|
|
die 0
|
|
elif ! net_connect; then
|
|
msg "Not Connected" "\nRunning live requires an active internet connection to install packages.\n\nExiting..\n" 2
|
|
die 1
|
|
elif (( $(awk '/MemTotal/ {print int($2 * 1024 / 1000 / 1000)}' /proc/meminfo) < 4704)); then
|
|
msg "Not Enough Memory" "\nLive session requires at least 4.5G of system memory for installing packages.\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
|
|
clear
|
|
echo "Sorting mirrorlist"
|
|
if ! mount /run/archiso/cowspace -o remount,size=4G; then
|
|
msg "Remount Fail" "\nUnable to remount root with a larger copy-on-write space, this is needed for installing packages.\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
install_mirrorlist "/etc/pacman.d/mirrorlist"
|
|
al_repo "/etc/pacman.conf"
|
|
pacman -Syyu --noconfirm || die 1
|
|
rm -rf /var/cache/pacman/pkg/*
|
|
local pkgs="${BASE_PKGS[*]}"
|
|
pacman -S ${pkgs/base-devel /} ${AL_PKGS[*]} xorg-xinit --needed --noconfirm || die 1
|
|
rm -rf /var/cache/pacman/pkg/*
|
|
case "$ses" in
|
|
$WM_PKG_SES) pacman -S "$ses" ${WM_PKGS[*]} ${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/*
|
|
[[ $VM ]] && dmesg | grep -qi 'vbox' && pacman -S virtualbox-guest-utils virtualbox-guest-modules-arch --needed --noconfirm
|
|
pacman -Scc --noconfirm
|
|
rm -rf /var/cache/pacman/pkg/*
|
|
cp -rfT /etc/skel /root
|
|
install_tearfree "/etc/X11/xorg.conf.d"
|
|
case "$ses" in
|
|
$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
|
|
sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
|
|
printf "\n%s has been set as the login session in ~/.xinitrc, to start the session simply run\n\n\tstartx\n\n" "${WM_SESSIONS[$ses]}"
|
|
die 0
|
|
}
|
|
|
|
usage()
|
|
{
|
|
cat <<- EOF
|
|
usage: $1 [-hdl] [session]
|
|
|
|
options:
|
|
-h, --help print this message and exit
|
|
-l, --live install and setup a live session
|
|
-d, --debug enable xtrace and log output to $DBG
|
|
-t, --tearfree install and setup drivers for nvidia or tearfree xorg configs for other vendors
|
|
if you experience boot issues with this option you can remove
|
|
/etc/X11/xorg.conf.d/20-*.conf
|
|
|
|
sessions:
|
|
i3-gaps - A fork of i3wm with more features including gaps
|
|
openbox - A lightweight, powerful, and highly configurable stacking wm
|
|
dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
|
|
awesome - A customized Awesome WM session created by @elanapan
|
|
bspwm - A tiling wm that represents windows as the leaves of a binary tree
|
|
fluxbox - A lightweight and highly-configurable window manager
|
|
jwm - A lightweight window manager for Xorg written in C
|
|
gnome - A desktop environment that aims to be simple and easy to use
|
|
cinnamon - A desktop environment combining traditional desktop with modern effects
|
|
plasma - A kde software project currently comprising a full desktop environment
|
|
xfce4 - A lightweight and modular desktop environment based on gtk+2/3
|
|
|
|
distro name:
|
|
|
|
set the DIST environment variable before launching the installer eg.
|
|
|
|
DIST='MyDistro' $1
|
|
|
|
root/boot partition:
|
|
|
|
set the ROOT and/or BOOT environment variables before launching the installer eg.
|
|
|
|
ROOT='/dev/sda2' BOOT='/dev/sda1' $1
|
|
|
|
editor used:
|
|
|
|
set the EDITOR environment variable before launching the installer eg.
|
|
|
|
EDITOR='nano' $1
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
yesno()
|
|
{
|
|
local title="$1" body="$2" yes='Yes' no='No'
|
|
(( $# >= 3 )) && yes="$3"
|
|
(( $# >= 4 )) && no="$4"
|
|
tput civis
|
|
if (( $# == 5 )); then
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
|
|
else
|
|
dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
|
|
fi
|
|
}
|
|
|
|
chrun()
|
|
{
|
|
arch-chroot "$MNT" bash -c "$1"
|
|
}
|
|
|
|
debug()
|
|
{
|
|
export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
|
|
set -x
|
|
exec 3>| $DBG
|
|
BASH_XTRACEFD=3
|
|
DEBUG=true
|
|
}
|
|
|
|
errmsg()
|
|
{
|
|
local err=""
|
|
|
|
err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
|
|
[[ -z $err ]] && err="no error message was found"
|
|
printf "%s" "$err"
|
|
}
|
|
|
|
al_repo()
|
|
{
|
|
local conf="$1"
|
|
|
|
grep -q 'archlabs_repo' "$conf" && return 0
|
|
|
|
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
|
|
}
|
|
|
|
termcol()
|
|
{
|
|
local colors=(
|
|
"\e]P0191919" # #191919
|
|
"\e]P1D15355" # #D15355
|
|
"\e]P2609960" # #609960
|
|
"\e]P3FFCC66" # #FFCC66
|
|
"\e]P4255A9B" # #255A9B
|
|
"\e]P5AF86C8" # #AF86C8
|
|
"\e]P62EC8D3" # #2EC8D3
|
|
"\e]P7949494" # #949494
|
|
"\e]P8191919" # #191919
|
|
"\e]P9D15355" # #D15355
|
|
"\e]PA609960" # #609960
|
|
"\e]PBFF9157" # #FF9157
|
|
"\e]PC4E88CF" # #4E88CF
|
|
"\e]PDAF86C8" # #AF86C8
|
|
"\e]PE2ec8d3" # #2ec8d3
|
|
"\e]PFE1E1E1" # #E1E1E1
|
|
)
|
|
|
|
[[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
|
|
}
|
|
|
|
errshow()
|
|
{
|
|
# shellcheck disable=SC2181
|
|
[ $? -eq 0 ] && return 0
|
|
|
|
local fatal=$1
|
|
shift # always shift off the fatal level arg
|
|
local txt
|
|
txt="\nCommand: $1\n\n\n\nError:\n$(errmsg)\n\n"
|
|
tput cnorm
|
|
if (( fatal )); then
|
|
yesno "Install Error" "${txt}Errors at this stage must be fixed before the install can continue.\n$_errchoice" "Handle normally" "Continue, it's fixed" ||
|
|
return 0
|
|
[[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
|
|
die 1
|
|
fi
|
|
yesno "Install Error" "${txt}Errors at this stage may be fixed or ignored depending on the error.\n$_errchoice" "Handle normally" "Continue, it's fixed" &&
|
|
return 1
|
|
return 0
|
|
}
|
|
|
|
prechecks()
|
|
{
|
|
local i=1
|
|
|
|
if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
|
|
msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
|
|
SEL=4 i=0
|
|
elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
|
|
msg "No Bootloader" "\nBootloader must be selected first.\n" 2
|
|
SEL=5 i=0
|
|
elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
|
|
msg "No User" "\nA user must be created first.\n" 2
|
|
SEL=6 i=0
|
|
elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
|
|
msg "Not Configured" "\nSystem configuration must be done first.\n" 2
|
|
SEL=7 i=0
|
|
fi
|
|
(( i )) # return code
|
|
}
|
|
|
|
umount_dir()
|
|
{
|
|
mount | grep -q 'swap' && swapoff -a
|
|
for dir; do
|
|
if [[ -d $dir ]] && mount | grep -q "on $dir "; then
|
|
if ! umount "$dir" 2> /dev/null; then
|
|
sleep 0.5
|
|
umount -f "$dir" 2> /dev/null || umount -l "$dir"
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
chk_connect()
|
|
{
|
|
msg "Network Connect" "\nVerifying network connection\n" 0
|
|
if [[ $VM ]] && hash nm-online > /dev/null 2>&1; then
|
|
nm-online > /dev/null 2>&1
|
|
else
|
|
ping -qc1 'archlinux.org' > /dev/null 2>&1
|
|
fi
|
|
}
|
|
|
|
net_connect()
|
|
{
|
|
if chk_connect; then
|
|
return 0
|
|
elif hash nmtui > /dev/null 2>&1; then
|
|
tput civis
|
|
if [[ $TERM == 'linux' ]]; then
|
|
printf "%b" "\e]P1191919" "\e]P4191919" # fix up the nasty default colours of nmtui
|
|
nmtui-connect
|
|
printf "%b" "\e]P1D15355" "\e]P4255a9b" # restore defaults
|
|
else
|
|
nmtui-connect
|
|
fi
|
|
elif hash wifi-menu > /dev/null 2>&1; then
|
|
wifi-menu
|
|
else
|
|
return 1
|
|
fi
|
|
chk_connect
|
|
}
|
|
|
|
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
|
|
TryExec=dwm
|
|
Type=Application
|
|
EOF
|
|
}
|
|
|
|
is_bg_install()
|
|
{
|
|
[[ $BG_PID ]] || return 0
|
|
msg "Install Running" "\nA background install process is currently running.\n" 2
|
|
return 1
|
|
}
|
|
|
|
system_devices()
|
|
{
|
|
IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
|
|
|
|
SYS_DEVS="$(lsblk -lno TYPE,PATH,SIZE,MODEL | awk '/disk/ && !'"/${IGNORE_DEV:-NONEXX}/"' {print $2, $3 "__" $4}')"
|
|
|
|
if [[ -z $SYS_DEVS ]]; then
|
|
msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
|
|
DEV_COUNT=0
|
|
while read -r line; do
|
|
[[ "$line" ]] && (( DEV_COUNT++ ))
|
|
done <<< "$SYS_DEVS"
|
|
}
|
|
|
|
system_identify()
|
|
{
|
|
if [[ $VM ]]; then
|
|
UCODE=''
|
|
# amd-ucode is not needed it's provided by linux-firmware
|
|
# elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
|
|
# UCODE="amd-ucode"
|
|
elif grep -q 'GenuineIntel' /proc/cpuinfo; then
|
|
UCODE="intel-ucode"
|
|
fi
|
|
|
|
modprobe -q efivarfs > /dev/null 2>&1
|
|
|
|
if [[ -d /sys/firmware/efi/efivars ]]; then
|
|
export SYS="UEFI"
|
|
grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
|
|
else
|
|
export SYS="BIOS"
|
|
fi
|
|
}
|
|
|
|
###############################################################################
|
|
# entry point
|
|
|
|
# enable some nicer colours in the linux console
|
|
termcol
|
|
|
|
# ensure the required packages are installed and that we're running as root on x86_64 architecture
|
|
if ! hash dialog rsync find parted curl arch-chroot >/dev/null 2>&1; then
|
|
printf "One or more required packages are missing: dialog, curl, rsync, parted, findutils, arch-install-scripts"
|
|
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
|
|
msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
|
|
# trap ^C to perform cleanup
|
|
trap 'printf "\n^C\n" && die 1' INT
|
|
|
|
while getopts ":htl:d" OPT; do
|
|
case "$OPT" in
|
|
d) debug ;;
|
|
h) usage "$0" ;;
|
|
t) TEARFREE=true ;;
|
|
l)
|
|
if [[ "${!WM_SESSIONS[*]}" =~ $OPTARG ]]; then
|
|
live "$OPTARG"
|
|
else
|
|
echo "error: invalid session for -l, see -h for help"; die 1
|
|
fi
|
|
;;
|
|
\?) echo "error: invalid option: -$OPTARG"; die 1 ;;
|
|
esac
|
|
done
|
|
|
|
system_identify
|
|
system_devices
|
|
|
|
fontsize=16
|
|
while :; do
|
|
dlg fontsize menu "Font Size" "\nSelect a font size from the list below.\n\nDefault: 16" \
|
|
12 "setfont ter-i12n" 14 "setfont ter-i14n" 16 "setfont ter-i16n" 18 "setfont ter-i18n" \
|
|
20 "setfont ter-i20n" 22 "setfont ter-i22n" 24 "setfont ter-i24n" 28 "setfont ter-i28n" \
|
|
32 "setfont ter-i32n" || break
|
|
|
|
FONT="ter-i${fontsize}n"
|
|
setfont "$FONT"
|
|
yesno "Font Size" "\nKeep the currently set font size?\n" && break
|
|
done
|
|
|
|
msg "Welcome to the $DIST Installer" "$_welcome"
|
|
|
|
if ! select_keymap; then
|
|
clear
|
|
die 0
|
|
elif ! net_connect; then
|
|
msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
|
|
die 1
|
|
fi
|
|
|
|
while :; do
|
|
main
|
|
done
|
|
# vim:fdm=marker:fmr={,}
|