3 # This program is free software, provided under the GNU GPL
4 # Written by Nathaniel Maia for use in Archlabs
5 # Some ideas and code reworked from other resources
6 # AIF, Calamares, and the Arch Wiki.. Credit where credit is due
8 # check for syntax errors
15 : ${DIST=ArchLabs} # distro name if not set
16 MNT=/mnt # installation root mountpoint
17 ANS=/tmp/ans # dialog answer output file
18 FONT=ter-i16n # font used for the linux console
19 HOOKS=shutdown # additional mkinitcpio HOOKS
20 SEL=0 # currently selected menu item
21 SYS=Unknown # bios type, to be determined: UEFI/BIOS
22 BG=/tmp/bgout # output from background process
23 ERR=/tmp/errlog # stderr log used internally by errshow()
24 DBG=/tmp/debuglog # debug log file when passed -d
25 RUN=/run/archiso/bootmnt/arch/boot # path for live system /boot
26 VM="$(dmesg | grep -i hypervisor)" # system running in a virtual machine
27 EXMNTS="" # extra partitions that were mounted, used to verify mountpoint and show user
28 USER_CMD="" # optional command(s) entered by the user to run in the chroot
29 export DIALOGOPTS="--cr-wrap" # dialog environment variable to hold default options, see `man dialog`
31 BASE_PKGS="base xorg xorg-drivers sudo git gvfs gtk3 libmad libmatroska tumbler "
32 BASE_PKGS+="playerctl pulseaudio pulseaudio-alsa pavucontrol pamixer scrot xdg-user-dirs "
33 BASE_PKGS+="ffmpeg gstreamer gst-libav gst-plugins-base gst-plugins-good bash-completion xterm"
35 AL_BASE_PKGS="archlabs-keyring archlabs-icons archlabs-fonts archlabs-themes "
36 AL_BASE_PKGS+="archlabs-baph archlabs-wallpapers archlabs-scripts archlabs-skel-base"
38 WM_BASE_PKGS="arandr nitrogen polkit-gnome network-manager-applet "
39 WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool picom wmctrl feh "
40 WM_BASE_PKGS+="gnome-keyring dunst gsimplecal xfce4-power-manager xfce4-settings"
42 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
43 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
44 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
46 [[ $LINES ]] || LINES=$(tput lines)
47 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
51 # commands used to install each bootloader, however most get modified during runtime {
53 [refind-efi]='refind-install'
54 [grub]='grub-install --recheck --force' [syslinux]='syslinux-install_update -i -a -m'
55 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install'
58 # sessions that provide their own super bind and set the wallpaper {
59 declare SELF_CONTAINED='plasma|gnome|cinnamon|deepin'
60 declare SELF_CONTAINED_SES='startplasma-x11|gnome-session|startdde|cinnamon-session'
63 # executable name for each wm/de used in ~/.xinitrc {
64 declare -A WM_SESSIONS=(
65 [dwm]='dwm' [jwm]='jwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startplasma-x11' [xfce4]='startxfce4'
66 [deepin]='startdde' [gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session'
69 # packages installed for each wm/de, most are depends of the skel packages {
71 [dwm]='nitrogen polkit-gnome gnome-keyring dunst lxappearance' [jwm]='' [deepin]='deepin-extra'
72 [gnome]='gnome-tweaks' [cinnamon]='gnome-terminal' [plasma]='kde-applications-meta powerdevil'
73 [awesome]='archlabs-skel-awesome' [bspwm]='archlabs-skel-bspwm' [fluxbox]='archlabs-skel-fluxbox'
74 [i3-gaps]='archlabs-skel-i3-gaps' [openbox]='archlabs-skel-openbox' [xfce4]='archlabs-skel-xfce4 xfce4-goodies'
77 # files offered for editing after install is complete {
78 declare -A EDIT_FILES=(
79 [login]='' # login is populated once we know the username and shell
80 [fstab]='/etc/fstab' [sudoers]='/etc/sudoers' [crypttab]='/etc/crypttab' [pacman]='/etc/pacman.conf'
81 [console]='/etc/vconsole.conf' [mkinitcpio]='/etc/mkinitcpio.conf' [hostname]='/etc/hostname /etc/hosts'
82 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
83 [locale]='/etc/locale.conf /etc/default/locale' [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
86 # mkfs command flags for filesystem formatting {
87 declare -A FS_CMD_FLAGS=(
88 [f2fs]='' [jfs]='-q' [xfs]='-f' [ntfs]='-q' [ext2]='-q' [ext3]='-q' [ext4]='-q' [vfat]='-F32' [nilfs2]='-q' [reiserfs]='-q'
91 # mount options for each filesystem {
93 [vfat]='' [ntfs]='' [ext2]='' [ext3]='' # NA
94 [jfs]='discard errors=continue errors=panic nointegrity'
95 [reiserfs]='acl nolog notail replayonly user_xattr off'
96 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
97 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
98 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
99 [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'
102 # packages installed for each login option {
103 declare -A LOGIN_PKGS=(
104 [xinit]='xorg-xinit' [ly]='archlabs-ly' [gdm]='gdm' [sddm]='sddm'
105 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
108 # extras installed for user selected packages {
109 # if a package requires additional packages that aren't already dependencies
110 # they can be added here eg. [package]="extra"
112 [vlc]='qt4' [mpd]='mpc' [mupdf]='mupdf-tools'
113 [rxvt-unicode]='urxvt-perls' [zathura]='zathura-pdf-poppler' [noto-fonts]='noto-fonts-emoji' [cairo-dock]='cairo-dock-plug-ins' [qt5ct]='qt5-styleplugins'
114 [vlc]='qt5ct qt5-styleplugins' [qutebrowser]='qt5ct qt5-styleplugins' [qbittorrent]='qt5ct qt5-styleplugins' [transmission-qt]='qt5ct qt5-styleplugins'
115 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci' [kdenlive]='dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
118 # dialog text variables {
119 # Basics (somewhat in order)
120 _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"
121 _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"
122 _vconsole="\nSelect the console keymap, the console is the tty shell you reach before starting a graphical environment (Xorg).\n\nIts keymap is seperate from the one used by the graphical environments, though many do use the same such as 'us' English.\n\nSystem default: us"
123 _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 asterix (*) are required.\n\nOnce you're happy with the choices and the required steps are complete, selecting the final step will begin the install."
124 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
125 _resize="\nSelect a new filesystem size in MB, a new partition will be created from the free space but will be left unformatted.\nThe lowest size is just enough to fit the currently in use space on the partition while the default is set to split the free space evenly.\n\nUse Tab or the arrow keys move the cursor between the buttons and the value, when the cursor is on the value, you can edit it by:\n\n - left/right cursor movement to select a digit to modify\n - +/- characters to increment/decrement the digit by one\n - 0 through 9 to set the digit to the given value\n\nSome keys are also recognized in all cursor positions:\n\n - Home/End set the value to its maximum or minimum\n - Pageup/Pagedown increment the value so that the slider moves by one column."
126 _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."
127 _warn="\nIMPORTANT:\n\nChoose 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"
128 _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)."
129 _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."
130 _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."
131 _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."
132 _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"
133 _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."
134 _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."
135 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
136 _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."
137 _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 beggining or end."
138 _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"
139 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
140 _timesubz="\nSelect the nearest city to you or one with the same time zone.\n\nTIP: Pressing the first letter of the city name repeatedly will navigate between entries beggining with that letter."
141 _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."
142 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
143 _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"
144 _packages="\nUse [Space] to move a package into the selected area and press [Enter] to accept the selection.\n\nPackages may be installed by your DE/WM (if any), or for the packages you select."
145 _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"
146 _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."
149 _luksnew="Basic LUKS Encryption"
150 _luksadv="Advanced LUKS Encryption"
151 _luksopen="Open Existing LUKS Partition"
152 _luksmenu="\nA seperate 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."
153 _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."
154 _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)."
157 _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."
158 _lvmnew="Create Volume Group and Volume(s)"
159 _lvmdel="Delete an Existing Volume Group"
160 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
161 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
162 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
163 _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."
164 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
167 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
168 _errpart="\nYou need create the partiton(s) first.\n\n\nBIOS systems require at least one partition (ROOT).\n\nUEFI systems require at least two (ROOT and EFI).\n"
169 _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"
170 _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"
171 _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"
172 _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"
173 _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"
177 ###############################################################################
179 # main is the entry point which calls functions including outside of its block
180 # once those functions finished they always are returned here with the
181 # exception of install_main(), it exits upon completion
185 (( SEL < 13 )) && (( SEL++ ))
187 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
188 1 "Show device tree" \
190 3 "LUKS encryption" \
191 4 "Logical volume management" \
192 5 "* Mount partitions" \
193 6 "* Select bootloader" \
194 7 "* Username and password" \
195 8 "* System configuration" \
196 9 "Select window manager or desktop" \
197 10 "Select additional packages" \
198 11 "Run a command on the installed system" \
199 12 "View configuration and command selections" \
200 13 "* Confirm choices and start the installation" 2> "$ANS"
203 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
206 2) part_menu || (( SEL-- )) ;;
207 3) luks_menu || (( SEL-- )) ;;
208 4) lvm_menu || (( SEL-- )) ;;
209 5) mount_menu || (( SEL-- )) ;;
210 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
211 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
212 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
213 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
214 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
215 11) prechecks 3 && select_usercmd ;;
216 12) prechecks 3 && select_show ;;
217 13) prechecks 3 && install_main ;;
218 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
224 if [[ $SYS == 'BIOS' ]]; then
225 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
226 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
227 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
229 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
230 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
231 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
232 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
233 "efistub" "Boot the kernel image directly (no chainloading support)" \
234 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
241 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
242 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
243 pkgs="${pkgs// / }" pkgs="${pkgs# }"
244 msg "Show Configuration" "
245 ---------- PARTITION CONFIGURATION ------------
248 Boot Part: ${BOOT:-none}
249 Boot Device: ${BOOT_D:-none}
250 Swap Part/File: ${SWAP:-none}
251 Swap Size: ${SWAP_S:-none}
252 Extra Mounts: ${EXMNTS:-none}
253 Mkinit Hooks: ${HOOKS:-none}
255 LVM used: ${LVM:-unused}
256 LUKS used: ${LUKS:-unused}
258 ------------ SYSTEM CONFIGURATION -------------
260 Locale: ${LOCALE:-none}
261 Keymap: ${KEYMAP:-none}
262 Hostname: ${NEWHOST:-none}
263 Timezone: ${ZONE:-none}/${SUBZ:-none}
265 Chroot cmd: ${USER_CMD:-none}
267 ------------ USER CONFIGURATION ---------------
269 Username: ${NEWUSER:-none}
270 Login Shell: ${MYSHELL:-none}
271 Login Session: ${LOGIN_WM:-none}
272 Autologin: ${AUTOLOGIN:-none}
273 Login Type: ${LOGIN_TYPE:-none}
275 ----------- PACKAGE CONFIGURATION -------------
277 Kernel: ${KERNEL:-none}
278 Bootloader: ${BOOTLDR:-none}
279 Packages: ${pkgs:-none}
287 dlg LOGIN_TYPE menu "Login" "\nSelect what kind of login management to use." \
288 "xinit" "Console login without a display manager" \
289 "ly" "TUI display manager with a ncurses-like interface" \
290 "lightdm" "Lightweight display manager with a gtk greeter" \
291 "gdm" "Gnome display manager" \
292 "sddm" "Simple desktop display manager" || return 1
295 gdm|sddm) EDIT_FILES[login]="" ;;
296 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
298 LIGHTDM_GREETER='gtk-greeter'
299 EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
300 local txt="\nBecause you chose to install deepin you can choose to use their greeter for lightdm\n\nUse the deepin greeter?\n"
301 [[ $INSTALL_WMS == *deepin* ]] && yesno "Greeter" "$txt" && LIGHTDM_GREETER="deepin-greeter"
303 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
304 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
305 dlg LOGIN_WM menu "Session" "$_login" $LOGIN_CHOICES || return 1
306 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
308 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
309 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true
319 until [[ $CONFIG_DONE ]]; do
321 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
322 zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
323 bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
324 mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
326 1) dlg NEWHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
327 2) dlg LOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
329 until [[ $ZONE && $SUBZ ]]; do
330 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
331 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
333 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
334 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
335 linux 'Vanilla linux kernel and modules, with a few patches applied' \
336 linux-lts 'Long-term support (LTS) linux kernel and modules' \
337 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
338 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
342 (( i++ )) # progress through to the next choice
346 bash) LOGINRC='.bash_profile' ;;
347 zsh) LOGINRC='.zprofile' ;;
348 mksh) LOGINRC='.profile' ;;
359 until [[ $NEWUSER ]]; do
361 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
362 "Username:" 1 1 "${ans[0]}" 1 11 "$COLUMNS" 0 0 \
363 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
364 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
365 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
366 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
367 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2> "$ANS" || return 1
369 mapfile -t ans <"$ANS"
371 # root passwords empty, so use the user passwords
372 if [[ -z "${ans[4]}" && -z "${ans[5]}" ]]; then
377 # make sure a username was entered and that the passwords match
378 if [[ -z ${ans[0]} || ${ans[0]} =~ \ |\' || ${ans[0]} =~ [^a-z0-9] ]]; then
379 msg "Invalid Username" "\nInvalid user name.\n\nPlease try again.\n"; u=''
380 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
381 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
382 elif [[ "${ans[4]}" != "${ans[5]}" ]]; then
383 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
386 USER_PASS="${ans[1]}"
387 ROOT_PASS="${ans[4]}"
395 dlg KEYMAP menu "Keyboard" "$_keymap" \
396 us English cm English gb English au English gh English \
397 za English ng English ca French 'cd' French gn French \
398 tg French fr French de German at German ch German \
399 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
400 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
401 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
402 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
403 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
404 dk Danish be Belgian in Indian al Albanian am Armenian \
405 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
406 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
407 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
408 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
409 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
410 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
411 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
412 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
413 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
414 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
415 me Montenegrin || return 1
417 if [[ $CMAPS == *"$KEYMAP"* ]]; then
420 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
423 if [[ $TERM == 'linux' ]]; then
424 loadkeys "$CMAP" > /dev/null 2>&1
426 setxkbmap "$KEYMAP" > /dev/null 2>&1
434 dlg USER_CMD input "Command" "$_usercmd" "$USER_CMD" nolimit
440 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
441 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
442 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
443 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
444 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
445 jwm "A lightweight window manager for Xorg written in C" "$(ofn jwm "${INSTALL_WMS[*]}")" \
446 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
447 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
448 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
449 plasma "A KDE software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
450 deepin "The desktop environment of the Chinese Deepin Linux distribution." "$(ofn deepin "${INSTALL_WMS[*]}")" \
451 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
452 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
454 [[ $INSTALL_WMS ]] || return 0
455 WM_PKGS="${INSTALL_WMS/dwm/}"
456 WM_PKGS="${WM_PKGS// / }"
457 WM_PKGS="${WM_PKGS# }"
459 for i in $INSTALL_WMS; do
460 LOGIN_CHOICES+="$i - "
461 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
464 select_login || return 1
466 while IFS=' ' read -r pkg; do
467 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
475 dlg USER_PKGS check " Packages " "$_packages" \
476 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
477 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
478 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
479 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
480 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
481 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
482 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
483 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
484 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
485 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
486 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
487 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
488 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
489 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
490 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
491 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
492 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
493 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
494 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
495 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
496 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
497 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
498 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
499 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
500 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
501 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
502 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
503 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
504 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
505 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
506 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
507 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
508 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
509 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
510 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
511 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
512 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
513 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
514 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
515 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
516 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
517 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
518 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
519 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
520 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
521 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
522 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
523 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
524 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
525 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
526 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
527 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
528 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
529 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
530 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
531 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
532 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
533 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
534 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
535 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
536 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
537 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
538 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
539 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
540 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
541 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
542 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
543 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
544 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
545 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
546 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
547 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
548 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
549 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
550 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
551 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
552 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
553 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
554 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
555 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
556 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
557 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
558 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
559 xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
560 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
561 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
563 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
564 for i in $USER_PKGS; do
565 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
572 ###############################################################################
574 # non-essential partitioning helpers called by the user when using the optional
575 # partition menu and selecting a device to edit
579 is_bg_install || return 0
580 local device choice devhash
581 devhash="$(lsblk -f | base64)"
583 part_device || return 1
588 dlg choice menu "Edit Partitions" "$_part\n\n$(lsblk -no NAME,MODEL,SIZE,TYPE,FSTYPE $device)" \
589 "auto" "Whole device automatic partitioning" \
590 "cfdisk" "Curses based variant of fdisk" \
591 "parted" "GNU partition editor" $([[ $DISPLAY ]] && hash gparted >/dev/null 2>&1 && printf "gparted 'A gui front end to parted'") \
592 "fdisk" "Dialog-driven creation and manipulation of partitions" \
593 "done" "Return to the main menu"
594 # "shrink" "Shrink an existing ext or ntfs partition" \
596 if [[ -z $choice || $choice == 'done' ]]; then
598 elif [[ $choice == 'shrink' ]]; then
599 part_shrink "$device"
600 elif [[ $choice == 'auto' ]]; then
601 local root_size txt label boot_fs boot_type
602 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"}}')
603 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
604 if [[ $SYS == 'BIOS' ]]; then
605 label="msdos" boot_fs="ext4" boot_type="primary"
606 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
608 label="gpt" boot_fs="fat32" boot_type="ESP"
609 txt+="A $boot_fs efi boot partition (512M)\n- "
611 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
612 yesno "Auto Partition" "$txt" && part_auto "$device" "$label" "$boot_fs" "$root_size" "$boot_type"
618 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
619 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
620 partprobe > /dev/null 2>&1
621 [[ $choice == 'auto' ]] && return
629 if [[ $IGNORE_DEV ]]; then
630 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
632 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
634 msg "Device Tree" "\n\n$txt\n\n"
639 local device="$1" label="$2" boot_fs="$3" size="$4" boot_type="$5" dev_info=""
641 msg "Auto Partition" "\nRemoving partitions on $device and setting label to $label\n" 1
643 dev_info="$(parted -s "$device" print 2> /dev/null)"
646 while read -r PART; do
647 [[ $PART ]] || continue
648 parted -s "$device" rm "$PART" > /dev/null 2> "$ERR"
649 errshow 0 "parted -s $device rm $PART" || return 1
650 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
652 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$label" ]] && parted -s "$device" mklabel "$label" > /dev/null 2> "$ERR"
654 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
655 parted -s "$device" mkpart "$boot_type" "$boot_fs" 1MiB 513MiB > /dev/null 2> "$ERR"
656 errshow 0 "parted -s $device mkpart $boot_type $boot_fs 1MiB 513MiB" || return 1
660 AUTO_BOOT=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
662 if [[ $SYS == "BIOS" ]]; then
663 mkfs.ext4 -q "$AUTO_BOOT" > /dev/null 2> "$ERR"
664 errshow 0 "mkfs.ext4 -q $AUTO_BOOT" || return 1
666 mkfs.vfat -F32 "$AUTO_BOOT" > /dev/null 2> "$ERR"
667 errshow 0 "mkfs.vfat -F32 $AUTO_BOOT" || return 1
670 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
671 parted -s "$device" mkpart primary ext4 513MiB 100% > /dev/null 2> "$ERR"
672 errshow 0 "parted -s $device mkpart primary ext4 513MiB 100%" || return 1
674 AUTO_ROOT="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
675 mkfs.ext4 -q "$AUTO_ROOT" > /dev/null 2> "$ERR"
676 errshow 0 "mkfs.ext4 -q $AUTO_ROOT" || return 1
678 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
685 local device="$1" fs=""
687 part_find "${device##*/}[^ ]" || return 1
688 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
690 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
691 fs=$(lsblk -lno FSTYPE "$part")
694 msg "Resize" "\nGathering device size info.\n" 0
696 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
697 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
698 mount "$part" "$MNT" > /dev/null 2>&1; sleep 0.5
699 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
700 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
703 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2> $ANS; then
705 size=$((size * 1024))
712 if ntfsresize -fc "$part"; then
713 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2> "$ERR" # k=10^3 bytes
714 errshow 0 "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
716 msg "Resize" "\nThe ntfs partition $part cannot be resized because it is scheduled for a consistency check.\n\nTo do a consistency check in windows open command prompt as admin and run:\n\n\tchkdsk /f /r /x\n"
721 e2fsck -f "$part"; sleep 0.5
722 resize2fs -f "$part" ${size}K 2> "$ERR" # K=2^10 bytes
723 errshow 0 "resize2fs -f $part ${size}K" || return 1
727 parted "$device" resizepart "$num" ${size}KiB || return 1
730 if [[ $devsize == "$end" ]]; then
731 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2> "$ERR"
732 errshow 0 "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
734 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2> "$ERR"
735 errshow 0 "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
737 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
739 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
740 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
745 ###############################################################################
746 # partition management functions
747 # these are helpers for use by other functions to do essential setup/teardown
751 local regexp="$1" err=''
752 local pts dev size isize ptcount=0
754 # string of partitions as /TYPE/PART SIZE.. eg. /dev/sda1 256G
755 if [[ $IGNORE_DEV ]]; then
756 PARTS="$(lsblk -lno TYPE,NAME,SIZE | awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {sub(/^part/, "/dev/"); sub(/^lvm|^crypt/, "/dev/mapper/"); print $1$2, $3}')"
758 PARTS="$(lsblk -lno TYPE,NAME,SIZE | awk "/$regexp/"' {sub(/^part/, "/dev/"); sub(/^lvm|^crypt/, "/dev/mapper/"); print $1$2 " " $3}')"
761 # ensure we have enough partitions for the system and action were trying to do
762 COUNT=$(wc -l <<< "$PARTS")
764 while read -r dev size; do # walk partition list and skip ones that are too small
765 [[ $dev && $size ]] || continue
766 size_t="${size: -1:1}"
769 [[ $size_t == 'K' || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
773 'part|lvm|crypt') [[ $ptcount -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
774 'part|crypt') (( ptcount < 1 )) && err="$_lvmerr" ;;
775 'part|lvm') (( ptcount < 2 )) && err="$_lukserr" ;;
779 msg "Not Enough Partitions" "$err" 2
788 if [[ $1 == "$MNT/swapfile" && $SWAP_S ]]; then
789 fallocate -l $SWAP_S "$1" 2> "$ERR"
790 errshow 0 "fallocate -l $SWAP_S $1"
791 chmod 600 "$1" 2> "$ERR"
792 errshow 0 "chmod 600 $1"
794 mkswap "$1" > /dev/null 2> "$ERR"
795 errshow 0 "mkswap $1"
796 swapon "$1" > /dev/null 2> "$ERR"
797 errshow 0 "swapon $1"
804 local mntpt="${MNT}$2"
806 local fs="$(lsblk -lno FSTYPE "$part")"
810 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT" && $part != "$AUTO_ROOT" ]] && select_mntopts "$fs"; then
811 mount -o "$MNT_OPTS" "$part" "$mntpt" > /dev/null 2> "$ERR"
812 errshow 0 "mount -o $MNT_OPTS $part $mntpt" || return 1
814 mount "$part" "$mntpt" > /dev/null 2> "$ERR"
815 errshow 0 "mount $part $mntpt" || return 1
818 msg "Mount Complete" "\nPartition $part mounted at $mntpt\n" 1
819 part_countdec "$part"
832 msg "Format" "\nFormatting $part as $fs\n" 0
833 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" > /dev/null 2> "$ERR"
834 errshow 0 "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1
840 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
841 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
842 elif (( DEV_COUNT > 1 )); then
844 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
846 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
848 [[ $DEVICE ]] || return 1
849 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
850 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
854 [[ $1 ]] && BOOT_D="$DEVICE"
861 BOOT_D="${BOOT%[1-9]}"
862 BOOT_NUM="${BOOT: -1}"
863 [[ $BOOT = /dev/nvme* ]] && BOOT_D="${BOOT%p[1-9]}"
864 if [[ $SYS == 'UEFI' ]]; then
865 parted -s $BOOT_D set $BOOT_NUM esp on > /dev/null 2>&1
867 parted -s $BOOT_D set $BOOT_NUM boot on > /dev/null 2>&1
874 local part="$1" devs=""
875 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
877 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
878 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
880 LUKS_NAME="${part#/dev/mapper/}"
881 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
882 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
883 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
888 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
889 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
890 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
891 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
895 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
897 VNAME="${part#/dev/mapper/}"
898 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
899 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
900 LUKS_NAME="${dev/\/dev\/mapper\//}"
904 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
905 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
906 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
907 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
919 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
925 ###############################################################################
927 # mount_menu is the entry point which calls all other functions
928 # once finished it returns to the main menu: main()
932 msg "Mount Menu" "\nGathering device and partition information.\n" 1
933 is_bg_install || return 0
936 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
937 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
938 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
939 select_root || { ROOT=''; return 1; }
940 select_boot || { BOOT=''; return 1; }
942 part_mount "$BOOT" "/boot" || return 1
946 select_swap || return 1
947 select_extra || return 1
954 local pts dev size isize ptcount=0
956 if [[ -z $BOOT ]]; then
957 if [[ $AUTO_BOOT && -z $LVM && -z $LUKS ]]; then
963 while read -r dev size; do # walk partition list and skip ones that are too small/big for boot
964 size_t="${size: -1:1}"
967 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
974 0) msg "EFI Boot Partition" "\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;;
975 1) msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;;
976 *) dlg BOOT menu "EFI Partition" "$_uefi" $pts ;;
978 [[ $BOOT ]] || return 1
981 if [[ $LUKS && ! $LVM ]]; then
983 0) msg "Boot Partition" "\nLUKS without LVM requires a separate boot partition.\nNo partitions available that meet size requirements!!\n\nReturning to the main menu.\n" 2; return 1 ;;
984 1) msg "Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1; BOOT="$(awk 'NF > 0 {print $1}' <<< "$pts")" ;;
985 *) dlg BOOT menu "Boot Partition" "$_biosluks" $pts ;;
987 [[ $BOOT ]] || return 1
989 (( ptcount == 0 )) && return 0
990 dlg BOOT menu "Boot Partition" "$_bios" "skip" "no separate boot" $pts
991 [[ -z $BOOT || $BOOT == "skip" ]] && { BOOT=''; return 0; }
997 if ([[ $SYS == 'BIOS' ]] && grep -q 'ext[34]' <<< "$(fsck -N "$BOOT")") || ([[ $SYS == 'UEFI' ]] && grep -q 'fat' <<< "$(fsck -N "$BOOT")"); then
998 yesno "Format Boot Partition" "\nIMPORTANT:\n\nThe boot partition $BOOT $_format" "Format $BOOT" "Skip Formatting" 1 || return 0
1002 UEFI) part_format "$BOOT" "vfat" 2 || return 1 ;;
1003 BIOS) part_format "$BOOT" "ext4" 2 || return 1 ;;
1010 if [[ -z $ROOT ]]; then
1011 if [[ $AUTO_ROOT && -z $LVM && -z $LUKS ]]; then
1013 msg "Mount Menu" "\nUsing partitions created during automatic format.\n" 2
1014 part_mount "$ROOT" || { ROOT=''; return 1; }
1015 return 0 # we're done here
1017 local pts dev size isize ptcount=0
1019 # walk partition list and skip ones that are too small for / (root)
1020 while read -r dev size; do
1021 size_t="${size: -1:1}" # size type eg. K, M, G, T
1022 isize=${size:0:-1} # remove trailing size type character
1023 isize=${isize%.*} # remove any decimal (round down)
1024 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1027 if (( ptcount == 1 )); then # only one available device
1028 msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1029 ROOT="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1031 local txt="\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 4G will not be shown here."
1032 dlg ROOT menu "Mount Root" "$txt" $pts
1037 [[ $ROOT ]] && select_filesystem "$ROOT" && part_mount "$ROOT" "" && return 0
1039 # should never reach here unless an error occurred
1046 local pts dev size isize
1048 if (( COUNT )) ; then
1049 while read -r dev size; do # walk partition list and skip ones that are too small/big for swap
1050 size_t="${size: -1:1}"
1053 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 16) || ($size_t == 'M' && $isize -lt 100) ]] || pts+="$dev $size "
1057 dlg SWAP menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1058 "none" "Don't allocate any swap space" \
1059 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1062 if [[ -z $SWAP || $SWAP == "none" ]]; then
1065 elif [[ $SWAP == "swapfile" ]]; then
1067 until [[ ${SWAP_S:0:1} =~ [1-9] && ${SWAP_S: -1} =~ (M|G) ]]; do
1068 (( i > 0 )) && msg "Swap Size Error" "\nSwap size must be 1(M|G) or greater, and can only contain whole numbers\n\nSize entered: $SWAP_S\n" 2
1069 dlg SWAP_S input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP=''; SWAP_S=''; return 1; }
1072 part_swap "$MNT/$SWAP"
1076 part_countdec "$SWAP"
1077 SWAP_S="$(lsblk -lno SIZE $SWAP)"
1086 # walk partition list and skip ones that are too small to be usable
1087 if (( COUNT )); then
1088 while read -r dev size; do
1089 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1093 while (( COUNT )); do
1095 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1096 if [[ $part == 'done' ]]; then
1098 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1099 EXMNTS+="$part: $EXMNT "
1100 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS+=" usr"
1106 (( COUNT == 0 )) && msg "Mount Extra" "\nMounting Finished\n\nNo more partitions to mount, returning to main menu.\n" 2
1114 local title="${fs^} Mount Options"
1116 for i in ${FS_OPTS[$fs]}; do
1120 until [[ $MNT_OPTS ]]; do
1121 dlg MNT_OPTS check "$title" "$_mount" $opts
1122 [[ $MNT_OPTS ]] || return 1
1123 MNT_OPTS="${MNT_OPTS// /,}"
1124 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1133 local cur="$(lsblk -lno FSTYPE "$part" 2> /dev/null)"
1134 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1136 # bail early if the partition was created in part_auto()
1137 [[ $cur && $part == "$AUTO_ROOT" ]] && return 0
1140 if [[ $cur && $part != "$ROOT" ]]; then
1141 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1143 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1145 [[ $fs == 'skip' ]] && return 0
1146 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1148 part_format "$part" "$fs" 0
1154 until [[ $EXMNT ]]; do
1155 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1156 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1157 msg "Mountpoint Error" "$_errexpart"
1164 ###############################################################################
1166 # main is the entry point which calls all other install functions, once
1167 # complete it shows a dialog to edit files on the new system before reboot
1172 genfstab -U "$MNT" > "$MNT/etc/fstab" 2> "$ERR"
1173 errshow 1 "genfstab -U $MNT > $MNT/etc/fstab"
1174 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" "$MNT/etc/fstab"
1176 install_tearfree "$MNT/etc/X11/xorg.conf.d"
1179 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1182 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1183 if [[ "$USER_CMD" ]]; then
1184 chrun "$USER_CMD" 2> "$ERR" 2>&1
1185 errshow 0 "$USER_CMD"
1189 dlg choice menu "Finalization" "$_edit" \
1190 finished "exit the installer and reboot" \
1191 keyboard "${EDIT_FILES[keyboard]}" \
1192 console "${EDIT_FILES[console]}" \
1193 locale "${EDIT_FILES[locale]}" \
1194 hostname "${EDIT_FILES[hostname]}" \
1195 sudoers "${EDIT_FILES[sudoers]}" \
1196 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1197 fstab "${EDIT_FILES[fstab]}" \
1198 crypttab "${EDIT_FILES[crypttab]}" \
1199 bootloader "${EDIT_FILES[bootloader]}" \
1200 pacman "${EDIT_FILES[pacman]}" \
1201 login "${EDIT_FILES[login]}"
1203 if [[ -z $choice || $choice == 'finished' ]]; then
1204 [[ $DEBUG == true && -r $DBG ]] && ${EDITOR:-vim} "$DBG"
1209 for f in ${EDIT_FILES[$choice]}; do
1210 if [[ -e ${MNT}$f ]]; then
1211 ${EDITOR:-vim} "${MNT}$f"
1213 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${MNT}$f\n"
1226 if [[ $BG_PID ]] && kill -0 $BG_PID 2> /dev/null; then
1227 printf "\nA background install process is still running, tailing the output...\n"
1228 tail -f --pid=$BG_PID "$BG"
1234 rm -rf "$MNT/etc/mkinitcpio-archiso.conf"
1235 find "$MNT/usr/lib/initcpio" -name 'archiso*' -type f -delete
1237 # remove/disable customizations done to airootfs during building
1238 chrun "systemctl disable pacman-init.service choose-mirror.service" > /dev/null 2>&1
1239 rm -f "$MNT/etc/systemd/scripts/choose-mirror"
1240 rm -f "$MNT/etc/systemd/system/"{choose-mirror.service,etc-pacman.d-gnupg.mount,pacman-init.service}
1241 sed -i 's/#\(Storage=\)volatile/\1auto/' "$MNT/etc/systemd/journald.conf"
1242 sed -i 's/#\(HandleSuspendKey=\)ignore/\1suspend/' "$MNT/etc/systemd/logind.conf"
1243 sed -i 's/#\(HandleHibernateKey=\)ignore/\1hibernate/' "$MNT/etc/systemd/logind.conf"
1244 sed -i 's/#\(HandleLidSwitch=\)ignore/\1suspend/' "$MNT/etc/systemd/logind.conf"
1245 find "$MNT/boot" -name '*-ucode.img' -delete
1247 # changing distro name?
1248 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" "$MNT/etc/"{lsb-release,os-release}
1250 # vmlinuz, if this isn't copied the standard kernel may fail mkinitcpio
1251 cp -vf "$RUN/x86_64/vmlinuz" "$MNT/boot/vmlinuz-linux" 2> "$ERR" 2>&1
1252 errshow 1 "cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux"
1254 # copy network settings
1255 [[ -d /etc/netctl ]] && cp -rfv /etc/netctl "$MNT/etc/"
1256 [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf "$MNT/etc/"
1257 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections "$MNT/etc/NetworkManager/"
1259 echo "LANG=$LOCALE" > "$MNT/etc/locale.conf"
1260 cp -fv "$MNT/etc/locale.conf" "$MNT/etc/default/locale"
1261 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${LOCALE}/${LOCALE}/g" "$MNT/etc/locale.gen"
1263 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1265 cat > "$MNT/etc/X11/xorg.conf.d/00-keyboard.conf" <<- EOF
1266 # Use localectl(1) to instruct systemd-localed to update it.
1267 Section "InputClass"
1268 Identifier "system-keyboard"
1269 MatchIsKeyboard "on"
1270 Option "XkbLayout" "$KEYMAP"
1274 cat > "$MNT/etc/default/keyboard" <<- EOF
1275 # KEYBOARD CONFIGURATION FILE
1276 # Consult the keyboard(5) manual page.
1283 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > "$MNT/etc/vconsole.conf"
1285 echo "$NEWHOST" > "$MNT/etc/hostname"
1286 cat > "$MNT/etc/hosts" <<- EOF
1289 ::1 localhost ip6-localhost ip6-loopback
1290 ff02::1 ip6-allnodes
1291 ff02::2 ip6-allrouters
1297 echo "Installing $BOOTLDR"
1299 if [[ $ROOT == /dev/mapper* ]]; then
1302 local uuid_type="UUID"
1303 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1304 ROOT_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT)"
1307 if [[ $SYS == 'UEFI' ]]; then
1308 # remove our old install and generic BOOT/ dir
1309 echo "Removing conflicting boot directories"
1310 find "$MNT/boot/EFI/" -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete -printf "remove %p\n"
1311 find "$MNT/boot/EFI/" -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete -printf "remove %p\n"
1315 chrun "${BCMDS[$BOOTLDR]}" 2> "$ERR" 2>&1
1316 errshow 1 "${BCMDS[$BOOTLDR]}"
1318 if [[ -d $MNT/hostrun ]]; then
1319 echo "Unmounting chroot directories"
1320 # cleanup the bind mounts we made earlier for the grub-probe module
1321 umount_dir "$MNT/hostrun/"{udev,lvm}
1322 rm -rf "$MNT/hostrun" > /dev/null 2>&1
1325 if [[ $SYS == 'UEFI' ]]; then
1326 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1327 mkdir -pv "$MNT/boot/EFI/BOOT"
1329 grub) cp -fv "$MNT/boot/EFI/$DIST/grubx64.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;;
1330 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" ;;
1332 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' "$MNT/boot/EFI/refind/refind.conf"
1333 cp -fv "$MNT/boot/EFI/refind/refind_x64.efi" "$MNT/boot/EFI/BOOT/BOOTX64.EFI" ;;
1342 local groups='audio,video,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1343 [[ -e $MNT/etc/X11/xorg.conf.d/20-nvida.conf && -e $MNT/usr/bin/optirun ]] && groups+=',bumblebee'
1345 rm -f "$MNT/root/.zlogin" # remove welcome message
1347 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2> "$ERR" 2>&1
1348 errshow 1 "set root password"
1349 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1350 chrun "usermod -s /bin/$MYSHELL root" 2> "$ERR" 2>&1
1351 errshow 1 "usermod -s /bin/$MYSHELL root"
1352 # copy the default mkshrc to /root if it was selected
1353 [[ $MYSHELL == 'mksh' ]] && cp -fv "$MNT/etc/skel/.mkshrc" "$MNT/root/.mkshrc"
1356 echo "Creating new user $NEWUSER and setting password"
1357 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2> "$ERR" 2>&1
1358 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1359 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2> "$ERR" 2>&1
1360 errshow 1 "set $NEWUSER password"
1362 [[ $INSTALL_WMS == *dwm* ]] && install_suckless "/home/$NEWUSER" chroot
1364 install_cleanup "$NEWUSER"
1371 AUTOLOGIN_SERV="$MNT/etc/systemd/system/getty@tty1.service.d"
1373 if [[ -z $LOGIN_TYPE ]]; then
1374 rm -rf "$AUTOLOGIN_SERV"
1378 echo "Setting up $LOGIN_TYPE"
1380 if [[ $LOGIN_TYPE != 'xinit' ]]; then
1381 [[ $INSTALL_WMS == *dwm* ]] && dwm_xsession
1382 rm -rf "$AUTOLOGIN_SERV" "$MNT/home/$NEWUSER/.xinitrc"
1383 chrun "systemctl enable $LOGIN_TYPE.service" 2> "$ERR" 2>&1
1384 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1387 ${LOGIN_TYPE}_config
1394 # remove tint2 and jgmenu configs if bspwm and openbox aren't being installed
1395 [[ $INSTALL_WMS =~ (bspwm|openbox) ]] || rm -rf "$MNT/home/$user/.config/"{jgmenu,tint2}
1397 # remove geany configs if it wasn't installed
1398 [[ $USER_PKGS != *geany* ]] && rm -rf "$MNT/home/$user/.config/geany"
1400 # remove shell stuff for unused shells
1401 [[ $MYSHELL != 'bash' ]] && rm -rf "$MNT/home/$user/.bash"*
1402 [[ $MYSHELL != 'zsh' ]] && rm -rf "$MNT/home/$user/.z"*
1404 # cleanup default jwmrc
1405 if [[ $INSTALL_WMS == *jwm* ]]; then
1406 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"
1409 # no picom (compton) or ksuperkey in dwm only installs
1410 [[ $LOGIN_WM == 'dwm' ]] && sed -i '/super/d; /picom/d' "$MNT/home/$user/.xprofile" "$MNT/root/.xprofile"
1412 # remove some commands from ~/.xprofile when using self contained sessions
1413 if [[ $LOGIN_WM =~ ($SELF_CONTAINED_SES) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ ($SELF_CONTAINED)) ]]; then
1414 sed -i '/super/d; /nitrogen/d; /picom/d' "$MNT/home/$user/.xprofile" "$MNT/root/.xprofile"
1422 local inpkg="$PACKAGES $USER_PKGS $AL_BASE_PKGS "
1424 if pacman -Qq archlabs-installer > /dev/null 2>&1; then
1425 rmpkg+="archlabs-installer "
1428 if [[ $MYSHELL == 'zsh' ]]; then
1429 inpkg+="zsh-completions "
1434 if [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox|jwm|awesome) ]]; then
1435 inpkg+="$WM_BASE_PKGS "
1436 elif [[ $INSTALL_WMS == 'dwm' ]]; then # dwm only needs a very limited package set
1440 # update and install crucial packages first to avoid issues
1441 al_repo "$MNT/etc/pacman.conf"
1442 chrun "pacman -Syyu $KERNEL $BASE_PKGS base-devel ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" 2> "$ERR" 2>&1
1443 errshow 1 "pacman -Syyu $KERNEL $BASE_PKGS base-devel ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed"
1445 # remove the packages we don't want on the installed system
1446 [[ $rmpkg ]] && chrun "pacman -Rnsc $rmpkg --noconfirm"
1448 # reinstalling iputils fixes the network issue for non-root users
1449 chrun "pacman -S iputils $UCODE --noconfirm"
1451 # install the packages chosen throughout the install
1452 chrun "pacman -S $inpkg --needed --noconfirm" 2> "$ERR" 2>&1
1453 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1455 # bootloader packages
1456 if [[ $BOOTLDR == 'grub' ]]; then
1457 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1458 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2> "$ERR" 2>&1
1459 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1460 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1461 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2> "$ERR" 2>&1
1462 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1463 elif [[ $SYS == 'UEFI' ]]; then
1464 chrun "pacman -S efibootmgr --needed --noconfirm" 2> "$ERR" 2>&1
1465 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1468 if [[ $VM ]] && dmesg | grep -qi 'vbox'; then
1470 linux) chrun "pacman -S virtualbox-guest-utils virtualbox-guest-modules-arch --needed --noconfirm" ;;
1471 *) chrun "pacman -S virtualbox-guest-utils virtualbox-guest-modules-dkms ${KERNEL}-headers --needed --noconfirm" ;;
1475 # allow members of the wheel group to run commands as root
1476 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" "$MNT/etc/sudoers"
1483 local dir="$1/suckless"
1486 if [[ $1 == 'chroot' ]]; then
1487 chrun "mkdir -pv '$dir'"
1488 for i in dwm dmenu st; do
1489 if chrun "git clone 'https://git.suckless.org/$i' '$dir/$i'"; then
1490 chrun "cd '$dir/$i' && make PREFIX=/usr install"
1492 printf "failed to clone %s repo\n" "$i"
1497 for i in dwm dmenu st; do
1498 if git clone "https://git.suckless.org/$i" "$dir/$i"; then
1499 cd "$dir/$i" && make PREFIX=/usr install
1501 printf "failed to clone %s repo\n" "$i"
1512 echo "Virtual machine detected, removing xorg configs"
1513 find "$xpath/" -name '*.conf' -delete -printf "remove %p\n"
1514 elif [[ $TEARFREE ]]; then
1515 if lspci | grep ' VGA ' | grep -q 'Intel'; then
1516 echo "Creating Intel Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1517 cat > "$xpath/20-intel.conf" <<- EOF
1519 Identifier "Intel Graphics"
1521 Option "TearFree" "true"
1524 cat "$xpath/20-intel.conf"
1525 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
1526 echo "Creating AMD Tear Free config /etc/X11/xorg.conf.d/20-amdgpu.conf"
1527 cat > "$xpath/20-amdgpu.conf" <<- EOF
1529 Identifier "AMD Graphics"
1531 Option "TearFree" "true"
1534 cat "$xpath/20-amdgpu.conf"
1535 elif lspci | grep ' VGA ' | grep -q 'AMD/ATI.*HD [2-6][0-9]*'; then # older HD 2xxx-6xxx cards must use the radeon driver
1536 echo "Creating Radeon Tear Free config /etc/X11/xorg.conf.d/20-radeon.conf"
1537 cat > "$xpath/20-radeon.conf" <<- EOF
1539 Identifier "AMD Graphics"
1541 Option "TearFree" "on"
1544 cat "$xpath/20-radeon.conf"
1545 elif lspci | grep ' VGA ' | grep -q 'NVIDIA'; then # nvidia cards require a bit of checking for notebook gpus
1546 echo "Trying nvidia driver install"
1547 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
1548 if [[ $xpath == *"$MNT"* ]]; then
1549 chrun "nvidia-installer --bumblebee"
1551 nvidia-installer --bumblebee
1554 if [[ $xpath == *"$MNT"* ]]; then
1555 chrun "nvidia-installer" # unsure which card so try auto detection
1560 if [[ -e $xpath/20-nvidia.conf ]]; then
1561 cat "$xpath/20-radeon.conf"
1563 echo "NVIDIA driver installed"
1564 if [[ $xpath == *"$MNT"* ]]; then
1565 echo "Trying to load the driver for live session"
1568 echo "To enable driver vsync:"
1569 echo -e "\trun nvidia-settings (as root) on first boot\n\tenable 'ForceFullCompositionPipeline' under the advanced settings"
1570 echo -e "\tlastly save the change to your nvida xorg config /etc/X11/xorg.conf.d/20-nvidia.conf"
1571 echo -e "\tand remove everything but the Device and Screen sections from the file"
1573 echo "Unable to install nvidia driver"
1578 if lspci | grep ' VGA ' | grep -q 'Intel\|AMD/ATI'; then
1579 if [[ $xpath == *"$MNT"* ]]; then
1580 sed -i 's/xrender/glx/g' "$MNT/etc/skel/.config/picom.conf"
1582 sed -i 's/xrender/glx/g' /etc/skel/.config/picom.conf
1587 # remove nvidia installer from installed system when not running nvidia gpu
1588 [[ $xpath == *"$MNT"* ]] && rm -rf "$MNT/usr/bin/nvidia-installer" "$MNT/var/lib/nvidia-installer"
1591 install_mkinitcpio()
1595 [[ $LUKS ]] && add+=" encrypt"
1596 [[ $LVM ]] && add+=" lvm2"
1597 sed -i "s/block filesystems/block${add} filesystems ${HOOKS}/g" "$MNT/etc/mkinitcpio.conf"
1598 chrun "mkinitcpio -p $KERNEL" 2> "$ERR" 2>&1
1599 errshow 1 "mkinitcpio -p $KERNEL"
1602 install_mirrorlist()
1604 if hash reflector > /dev/null 2>&1; then
1605 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1606 elif hash rankmirrors > /dev/null 2>&1; then
1607 echo "Sorting mirrorlist... This will take a while"
1608 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1609 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1610 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'])")"
1611 if [[ "$country" ]]; then
1612 if [[ $country =~ (CA|US) ]]; then
1613 # use both CA and US mirrors for CA or US countries
1614 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1615 elif [[ $country =~ (AU|NZ) ]]; then
1616 # use both AU and NZ mirrors for AU or NZ countries
1617 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1619 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1621 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1622 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1624 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - > "$1"
1628 install_background()
1631 rsync -a /run/archiso/sfs/airootfs/ "$MNT/" &&
1632 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" > /tmp/bgout 2>&1 &&
1633 al_repo "$MNT/etc/pacman.conf" &&
1634 chrun "pacman -Syyu $BASE_PKGS base-devel --noconfirm --needed" > /tmp/bgout 2>&1
1637 trap "kill $BG_PID 2> /dev/null" EXIT
1640 ###############################################################################
1641 # display manager config
1642 # these are called based on which DM is chosen after it is installed
1643 # additional config can be handled here, for now only lightdm and xinit.
1662 if [[ $INSTALL_WMS ]]; then
1663 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1664 if [[ $LOGIN_WM == 'gnome-session' ]]; then
1665 # see https://wiki.archlinux.org/index.php/GNOME#Manually
1666 sed -i '/exec/ i export XDG_SESSION_TYPE=x11' "$MNT/home/$NEWUSER/.xinitrc"
1667 sed -i '/exec/ i export GDK_BACKEND=x11' "$MNT/home/$NEWUSER/.xinitrc"
1670 rm -rf "$MNT/home/$NEWUSER/.xinitrc" "$MNT/root/.xinitrc"
1674 if [[ $AUTOLOGIN ]]; then
1675 mkdir -p "$AUTOLOGIN_SERV"
1676 cat > "$AUTOLOGIN_SERV/autologin.conf" <<- EOF
1679 ExecStart=-/sbin/agetty --autologin $NEWUSER --noclear %I 38400 linux
1681 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1682 # automatically run startx when logging in on tty1
1683 [ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ] && startx
1686 rm -rf "$AUTOLOGIN_SERV"
1692 sed -i "/greeter-session=/ c greeter-session=lightdm-$LIGHTDM_GREETER" "$MNT/etc/lightdm/lightdm.conf"
1694 if [[ $LIGHTDM_GREETER == 'gtk-greeter' ]]; then
1695 cat > "$MNT/etc/lightdm/lightdm-gtk-greeter.conf" <<- EOF
1697 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1698 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1699 theme-name=Adwaita-dark
1700 icon-theme-name=Adwaita
1701 font-name=DejaVu Sans Mono 11
1702 position=30%,end 50%,end
1707 ###############################################################################
1709 # prerun_* set up the configs needed before actually running the commands
1710 # setup_* are run after selecting a bootloader and build the command used later
1711 # they can also be used for further user input as these run before control is taken away
1715 EDIT_FILES[bootloader]="/etc/default/grub"
1717 if [[ $SYS == 'BIOS' ]]; then
1718 [[ $BOOT_D ]] || { part_device 1 || return 1; }
1719 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_D"
1721 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
1722 grub-install --recheck --force --target=x86_64-efi --efi-directory=/boot --bootloader-id=$DIST"
1723 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
1726 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1727 mount --bind /hostrun/udev /run/udev &&
1728 mount --bind /hostrun/lvm /run/lvm &&
1730 grub-mkconfig -o /boot/grub/grub.cfg &&
1731 sleep 1 && umount /run/udev /run/lvm"
1738 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" "$MNT/etc/default/grub"
1740 if [[ $LUKS_DEV ]]; then
1741 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" "$MNT/etc/default/grub" 2> "$ERR" 2>&1
1742 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1745 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1746 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" "$MNT/etc/default/grub" 2> "$ERR" 2>&1
1747 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1750 # setup for os-prober module
1751 mkdir -p /run/{lvm,udev} "$MNT/hostrun/"{lvm,udev}
1752 mount --bind /run/lvm "$MNT/hostrun/lvm"
1753 mount --bind /run/udev "$MNT/hostrun/udev"
1760 EDIT_FILES[bootloader]=""
1765 BCMDS[efistub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
1766 efibootmgr -v -d $BOOT_D -p $BOOT_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1767 -u 'root=$ROOT_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1772 if [[ $SYS == 'BIOS' ]]; then
1773 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1775 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1776 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1
1777 efibootmgr -v -c -d $BOOT_D -p $BOOT_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1783 local c="$MNT/boot/syslinux"
1784 local s="/usr/lib/syslinux/bios"
1786 if [[ $SYS == 'UEFI' ]]; then
1787 c="$MNT/boot/EFI/syslinux"
1788 s="/usr/lib/syslinux/efi64"
1791 mkdir -pv "$c" 2> "$ERR" 2>&1
1792 errshow 1 "mkdir -pv $c"
1793 cp -rfv "$s/"* "$c/" 2> "$ERR" 2>&1
1794 errshow 1 "cp -rfv $s/* $c/"
1795 cp -fv "$RUN/syslinux/splash.png" "$c/" 2> "$ERR" 2>&1
1796 errshow 0 "cp -fv $RUN/syslinux/splash.png $c/"
1797 cat > "$c/syslinux.cfg" <<- EOF
1799 MENU TITLE $DIST Boot Menu
1800 MENU BACKGROUND splash.png
1804 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1813 MENU HELPMSGENDROW 29
1814 MENU COLOR border 30;44 #40ffffff #a0000000 std
1815 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1816 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1817 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1818 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1819 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1820 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1821 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1822 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1825 MENU LABEL $DIST Linux
1826 LINUX $d/vmlinuz-$KERNEL
1827 APPEND root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1828 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1830 LABEL ${DIST}fallback
1831 MENU LABEL $DIST Linux Fallback
1832 LINUX $d/vmlinuz-$KERNEL
1833 APPEND root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1834 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1841 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1842 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1; refind-install"
1847 cat > "$MNT/boot/refind_linux.conf" <<- EOF
1848 "$DIST Linux" "root=$ROOT_ID $([[ $LUKS_DEV ]] &&
1849 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1850 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1851 "$DIST Linux Fallback" "root=$ROOT_ID $([[ $LUKS_DEV ]] &&
1852 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1853 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1855 mkdir -p "$MNT/etc/pacman.d/hooks"
1856 cat > "$MNT/etc/pacman.d/hooks/refind.hook" <<- EOF
1863 Description = Updating rEFInd on ESP
1864 When = PostTransaction
1865 Exec = /usr/bin/refind-install
1869 setup_systemd-boot()
1871 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1872 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars > /dev/null 2>&1; bootctl --path=/boot install"
1875 prerun_systemd-boot()
1877 mkdir -p "$MNT/boot/loader/entries"
1878 cat > "$MNT/boot/loader/loader.conf" <<- EOF
1883 cat > "$MNT/boot/loader/entries/$DIST.conf" <<- EOF
1885 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1886 initrd /initramfs-$KERNEL.img
1887 options root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1889 cat > "$MNT/boot/loader/entries/$DIST-fallback.conf" <<- EOF
1890 title $DIST Linux Fallback
1891 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1892 initrd /initramfs-$KERNEL-fallback.img
1893 options root=$ROOT_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1895 mkdir -p "$MNT/etc/pacman.d/hooks"
1896 cat > "$MNT/etc/pacman.d/hooks/systemd-boot.hook" <<- EOF
1903 Description = Updating systemd-boot
1904 When = PostTransaction
1905 Exec = /usr/bin/bootctl update
1907 systemd-machine-id-setup --root="$MNT"
1911 ###############################################################################
1916 is_bg_install || return 1
1920 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1921 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1922 "$_lvmdel" "vgremove -f" \
1923 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1924 "Back" "Return to the main menu"
1926 "$_lvmnew") lvm_create && break ;;
1927 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" > /dev/null 2>&1 ;;
1928 "$_lvmdelall") lvm_del_all ;;
1938 if [[ $(vgs -o vg_name --noheading 2> /dev/null) ]]; then
1939 if [[ $(lvs -o vg_name,lv_name --noheading --separator - 2> /dev/null) && $(pvs -o pv_name --noheading 2> /dev/null) ]]; then
1940 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1941 modprobe dm-mod > /dev/null 2> "$ERR"
1942 errshow 0 'modprobe dm-mod'
1943 vgscan > /dev/null 2>&1
1944 vgchange -ay > /dev/null 2>&1
1951 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1953 lvm_mkgroup || return 1
1954 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1955 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 -
1956 [[ $VOL_COUNT ]] || return 1
1957 lvm_extra_lvs || return 1
1958 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1959 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1960 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" > /dev/null 2> "$ERR"
1961 errshow 0 "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1962 LVM='logical volume'; sleep 0.5
1963 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1964 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1970 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1974 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1975 if [[ -z $VOLUME_SIZE ]]; then
1977 break # allow bailing with escape or an empty choice
1978 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1979 ERR_SIZE=1 # size values can't begin with '0'
1981 # walk the string and make sure all but the last char are digits
1982 local lv=$((${#VOLUME_SIZE} - 1))
1983 for (( i=0; i<lv; i++ )); do
1984 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1986 if (( ERR_SIZE != 1 )); then
1987 case ${VOLUME_SIZE:$lv:1} in
1989 local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1990 case ${VOLUME_SIZE:$lv:1} in
1992 if (( m >= VGROUP_MB )); then
1995 VGROUP_MB=$((VGROUP_MB - m))
1999 if (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )); then
2002 VGROUP_MB=$((VGROUP_MB - s))
2012 if (( ERR_SIZE )); then
2013 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
2026 until [[ $named ]]; do
2027 lvm_partitions || return 1
2028 lvm_group_name || return 1
2029 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
2032 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
2033 vgcreate -f "$VGROUP" $LVM_PARTS > /dev/null 2> "$ERR"
2034 errshow 0 "vgcreate -f $VGROUP $LVM_PARTS" || return 1
2036 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
2037 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
2039 if [[ $SIZE_UNIT == 'G' ]]; then
2040 VGROUP_MB=$((SIZE * 1000))
2045 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
2051 pv="$(pvs -o pv_name --noheading 2> /dev/null)"
2052 v="$(lvs -o vg_name,lv_name --noheading --separator - 2> /dev/null)"
2053 VGROUP="$(vgs -o vg_name --noheading 2> /dev/null)"
2055 if [[ $VGROUP || $v || $pv ]]; then
2056 if yesno "$_lvmdelall" "$_lvmdelask"; then
2057 for i in $v; do lvremove -f "/dev/mapper/$i" > /dev/null 2>&1; done
2058 for i in $VGROUP; do vgremove -f "$i" > /dev/null 2>&1; done
2059 for i in $pv; do pvremove -f "$i" > /dev/null 2>&1; done
2063 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
2073 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
2074 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
2077 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
2079 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2085 while (( VOL_COUNT > 1 )); do
2086 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
2087 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
2088 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" > /dev/null 2> "$ERR"
2089 errshow 0 "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2090 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2098 part_find 'part|crypt' || return 1
2099 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2100 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2107 until [[ $VGROUP ]]; do
2108 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
2109 if [[ -z $VGROUP ]]; then
2111 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
2112 msg "LVM Name Error" "$_lvmerrvgname"
2122 local txt="$1" default="mainvolume"
2123 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
2124 until [[ $VNAME ]]; do
2125 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2126 if [[ -z $VNAME ]]; then
2128 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2129 msg "LVM Name Error" "$_lvmerlvname"
2136 ###############################################################################
2142 is_bg_install || return 1
2143 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2144 "$_luksnew" "cryptsetup -q luksFormat" \
2145 "$_luksopen" "cryptsetup open --type luks" \
2146 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2147 "Back" "Return to the main menu"
2150 "$_luksnew") luks_basic || return 1 ;;
2151 "$_luksopen") luks_open || return 1 ;;
2152 "$_luksadv") luks_advanced || return 1 ;;
2160 modprobe -a dm-mod dm_crypt > /dev/null 2>&1
2162 part_find 'part|crypt|lvm' || return 1
2164 if (( COUNT == 1 )); then
2165 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2167 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2170 [[ $LUKS_PART ]] || return 1
2172 luks_pass "$_luksopen" || return 1
2173 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
2174 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
2175 errshow 0 "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2176 LUKS='encrypted'; luks_show
2184 typeset -a ans=(cryptroot) # default name to start
2186 until [[ $LUKS_PASS ]]; do
2188 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2189 "Name:" 1 1 "${ans[0]}" 1 7 "$COLUMNS" 0 0 \
2190 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2191 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2> "$ANS" || return 1
2193 mapfile -t ans <"$ANS"
2195 if [[ -z "${ans[0]}" ]]; then
2196 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2197 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
2198 LUKS_NAME="${ans[0]}"
2199 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2201 LUKS_NAME="${ans[0]}"
2202 LUKS_PASS="${ans[1]}"
2212 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2217 modprobe -a dm-mod dm_crypt > /dev/null 2>&1
2219 part_find 'part|lvm' || return 1
2221 if [[ $AUTO_ROOT ]]; then
2222 LUKS_PART="$AUTO_ROOT"
2223 elif (( COUNT == 1 )); then
2224 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2226 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2229 [[ $LUKS_PART ]] || return 1
2230 luks_pass "$_luksnew"
2235 luks_setup || return 1
2236 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2237 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2> "$ERR"
2238 errshow 0 "cryptsetup -q luksFormat $LUKS_PART" || return 1
2239 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
2240 errshow 0 "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2241 LUKS='encrypted'; luks_show
2249 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2250 [[ $cipher ]] || return 1
2251 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2252 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2> "$ERR"
2253 errshow 0 "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2254 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2> "$ERR"
2255 errshow 0 "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2262 ###############################################################################
2264 # some help avoid repetition and improve usability of some commands
2265 # others are initial setup functions used before reaching the main loop
2269 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2274 # cleanup and exit the installer cleanly with exit code $1
2275 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2279 if [[ -d $MNT ]]; then
2281 (( e == 127 )) && umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2288 local var="$1" # assign output from dialog to var
2289 local dlg_t="$2" # dialog type (menu, check, input)
2290 local title="$3" # dialog title
2291 local body="$4" # dialog message
2292 local n=0 # number of items to display for menu and check dialogs
2294 shift 4 # shift off args assigned above
2296 # adjust n when passed a large list
2297 local l=$((LINES - 20))
2298 (( ($# / 2) > l )) && n=$l
2302 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2> "$ANS" || return 1 ;;
2303 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2> "$ANS" || return 1 ;;
2306 local def="$1" # assign default value for input
2308 if [[ $1 == 'limit' ]]; then
2309 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2> "$ANS" || return 1
2311 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2> "$ANS" || return 1
2315 # if answer file isn't empty read from it into $var
2316 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2321 # displays a message dialog
2322 # when more than 2 args the message will disappear after sleep time ($3)
2328 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2330 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2338 if ! select_keymap; then
2341 elif ! net_connect; then
2342 msg "Not Connected" "\nRunning live requires an active internet connection to install packages.\n\nExiting..\n" 2
2344 elif (( $(awk '/MemTotal/ {print int($2 / 1024)}' /proc/meminfo) < 2500)); then
2345 msg "Not Enough Memory" "\nLive session requires at least 2.5G of system memory for installing packages.\n\nExiting..\n" 2
2350 echo "Sorting mirrorlist"
2351 mount /run/archiso/cowspace -o remount,size=2G
2352 install_mirrorlist "/etc/pacman.d/mirrorlist"
2353 al_repo "/etc/pacman.conf"
2354 pacman -Syyu --noconfirm || die 1
2355 rm -rf /var/cache/pacman/pkg/*
2356 pacman -S $BASE_PKGS $AL_BASE_PKGS xorg-xinit --needed --noconfirm || die 1
2357 rm -rf /var/cache/pacman/pkg/*
2359 i3-gaps|openbox|fluxbox|bspwm|awesome|xfce4|jwm) pacman -S "$ses" $WM_BASE_PKGS ${WM_EXT[$ses]} --needed --noconfirm || die 1 ;;
2360 $SELF_CONTAINED) pacman -S "$ses" ${WM_EXT[$ses]} --needed --noconfirm || die 1 ;;
2361 dwm) { pacman -S git --needed --noconfirm || die 1; }; install_suckless "/root" nochroot ;;
2363 rm -rf /var/cache/pacman/pkg/*
2364 [[ $VM ]] && dmesg | grep -qi 'vbox' && pacman -S virtualbox-guest-utils virtualbox-guest-modules-arch --needed --noconfirm
2365 pacman -Scc --noconfirm
2366 rm -rf /var/cache/pacman/pkg/*
2367 cp -rfT /etc/skel /root
2368 install_tearfree "/etc/X11/xorg.conf.d"
2370 $SELF_CONTAINED) sed -i '/super/d; /nitrogen/d; /picom/d' /root/.xprofile ;;
2371 dwm) sed -i '/super/d; /picom/d' /root/.xprofile ;;
2374 echo -e "pulseaudio &\n(sleep 1; pamixer --unmute --set-volume 50) &" >> /root/.xprofile
2375 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2376 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]}"
2383 usage: $1 [-hdl] [session]
2386 -h, --help print this message and exit
2387 -l, --live install and setup a live session
2388 -d, --debug enable xtrace and log output to $DBG
2389 -t, --tearfree install and setup drivers for nvidia or tearfree xorg configs for other vendors
2390 if you experience boot issues with this option you can remove
2391 /etc/X11/xorg.conf.d/20-*.conf
2394 i3-gaps - A fork of i3wm with more features including gaps
2395 openbox - A lightweight, powerful, and highly configurable stacking wm
2396 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2397 awesome - A customized Awesome WM session created by @elanapan
2398 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2399 fluxbox - A lightweight and highly-configurable window manager
2400 gnome - A desktop environment that aims to be simple and easy to use
2401 cinnamon - A desktop environment combining traditional desktop with modern effects
2402 plasma - A kde software project currently comprising a full desktop environment
2403 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2407 set the DIST environment variable before launching the installer eg.
2411 root/boot partition:
2413 set the ROOT and/or BOOT environment variables before launching the installer eg.
2415 ROOT='/dev/sda2' BOOT='/dev/sda1' $1
2419 set the EDITOR environment variable before launching the installer eg.
2429 local title="$1" body="$2" yes='Yes' no='No'
2430 (( $# >= 3 )) && yes="$3"
2431 (( $# >= 4 )) && no="$4"
2433 if (( $# == 5 )); then
2434 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2436 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2442 arch-chroot "$MNT" bash -c "$1"
2447 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2458 if ! grep -q 'archlabs_repo' "$conf"; then
2459 cat >> "$conf" <<- EOF
2462 Server = https://bitbucket.org/archlabslinux/\$repo/raw/master/\$arch
2465 Server = https://bitbucket.org/archlabslinux/\$repo/raw/master/\$arch
2466 Server = https://sourceforge.net/projects/archlabs-repo/files/\$repo/\$arch
2467 Server = https://github.com/ARCHLabs/\$repo/raw/master/\$arch
2477 "\e]P0191919" # #191919
2478 "\e]P1D15355" # #D15355
2479 "\e]P2609960" # #609960
2480 "\e]P3FFCC66" # #FFCC66
2481 "\e]P4255A9B" # #255A9B
2482 "\e]P5AF86C8" # #AF86C8
2483 "\e]P62EC8D3" # #2EC8D3
2484 "\e]P7949494" # #949494
2485 "\e]P8191919" # #191919
2486 "\e]P9D15355" # #D15355
2487 "\e]PA609960" # #609960
2488 "\e]PBFF9157" # #FF9157
2489 "\e]PC4E88CF" # #4E88CF
2490 "\e]PDAF86C8" # #AF86C8
2491 "\e]PE2ec8d3" # #2ec8d3
2492 "\e]PFE1E1E1" # #E1E1E1
2495 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2500 [ $? -eq 0 ] && return 0
2503 shift # always shift off the fatal level arg
2506 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2507 [[ -z $err ]] && err="no error message was found"
2509 local txt="\nCommand: $1\n\n\n\nError: $err\n\n"
2511 if (( fatal )); then
2512 msg "Install Error" "${txt}Errors at this stage are fatal, the install cannot continue.\n"
2513 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2517 msg "Install Error" "${txt}Errors at this stage are non-fatal and may be fixed or ignored depending on the error.\n"
2525 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2526 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2528 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2529 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2531 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2532 msg "No User" "\nA user must be created first.\n" 2
2534 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2535 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2538 (( i )) # return code
2543 mount | grep -q 'swap' && swapoff -a
2545 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2546 if ! umount "$dir" 2> /dev/null; then
2548 umount -f "$dir" 2> /dev/null || umount -l "$dir"
2556 msg "Network Connect" "\nVerifying network connection\n" 0
2557 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2562 if chk_connect; then
2564 elif hash nmtui > /dev/null 2>&1; then
2566 if [[ $TERM == 'linux' ]]; then
2567 printf "%b" "\e]P1191919" "\e]P4191919"
2569 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2574 elif hash wifi-menu > /dev/null 2>&1; then
2584 mkdir -p "$MNT/usr/share/xsessions"
2585 cat > "$MNT/usr/share/xsessions/dwm.desktop" <<- EOF
2589 Comment=Dynamic Window Manager
2597 [[ $BG_PID ]] || return 0
2598 msg "Install Running" "\nA background install process is currently running.\n" 2
2604 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2606 if [[ $IGNORE_DEV ]]; then
2607 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2609 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2612 if [[ -z $SYS_DEVS ]]; then
2613 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2618 while read -r line; do
2620 done <<< "$SYS_DEVS"
2627 # amd-ucode is not needed it's provided by linux-firmware
2628 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2630 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2634 modprobe -q efivarfs > /dev/null 2>&1
2636 if [[ -d /sys/firmware/efi/efivars ]]; then
2638 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2644 ###############################################################################
2647 # enable some nicer colours in the linux console
2650 # ensure the required packages are installed and that we're running as root on x86_64 architecture
2651 if ! hash dialog rsync find parted curl >/dev/null 2>&1; then
2652 printf "One or more of the required packages is missing: dialog, curl, rsync, parted, findutils"
2654 elif (( UID != 0 )); then
2655 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2657 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2658 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2662 # trap ^C to perform cleanup
2663 trap 'printf "\n^C\n" && die 1' INT
2665 while getopts ":htl:d" OPT; do
2671 if [[ "${!WM_SESSIONS[@]}" =~ $OPTARG ]]; then
2674 echo "error: invalid session for -l, see -h for help"; die 1
2677 \?) echo "error: invalid option: -$OPTARG"; die 1 ;;
2684 msg "Welcome to the $DIST Installer" "$_welcome"
2686 if ! select_keymap; then
2689 elif ! net_connect; then
2690 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2697 # vim:fdm=marker:fmr={,}