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, Cnichi, Calamares, Arch Wiki.. Credit where credit is due
10 # bulk default values {
12 : ${DIST=ArchLabs} # distro name if not set
13 MNT=/mnt # install mountpoint
14 ANS=/tmp/ans # dialog answer file
15 BOOTDIR=boot # location to mount boot partition
16 FONT=ter-i16n # font used for the linux console
17 HOOKS=shutdown # list of additional mkinitcpio HOOKS
18 SEL=0 # currently selected menu item
19 SYS=Unknown # bios type to be determined: UEFI/BIOS
20 ERR=/tmp/errlog # error log used internally
21 DBG=/tmp/debuglog # debug log when passed -d
22 RUN=/run/archiso/bootmnt/arch/boot # path for live system /boot
23 VM="$(dmesg | grep -i hypervisor)" # system running in a virtual machine
24 export DIALOGOPTS="--cr-wrap" # see `man dialog`
26 BASE_PKGS="base base-devel xorg xorg-drivers sudo git gvfs gtk3 libmad libmatroska tumbler "
27 BASE_PKGS+="playerctl pulseaudio pulseaudio-alsa pavucontrol pamixer scrot xdg-user-dirs "
28 BASE_PKGS+="ffmpeg gstreamer gst-libav gst-plugins-base gst-plugins-good bash-completion "
30 AL_BASE_PKGS="archlabs-keyring archlabs-icons archlabs-fonts archlabs-themes "
31 AL_BASE_PKGS+="archlabs-baph archlabs-wallpapers archlabs-scripts archlabs-skel-base"
33 WM_BASE_PKGS="arandr nitrogen polkit-gnome network-manager-applet "
34 WM_BASE_PKGS+="volumeicon xclip exo laptop-detect xdotool compton wmctrl feh "
35 WM_BASE_PKGS+="gnome-keyring dunst gsimplecal xfce4-power-manager xfce4-settings"
37 SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024) "M"}' /proc/meminfo)"
38 LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if ($1) {print $1 " - "}}' /etc/locale.gen)"
39 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " - "}' | sort)"
41 [[ $LINES ]] || LINES=$(tput lines)
42 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
46 # commands used to install each bootloader, however most get modified during runtime {
48 [refind-efi]='refind-install'
49 [grub]='grub-install --recheck --force' [syslinux]='syslinux-install_update -i -a -m'
50 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l' [systemd-boot]='bootctl --path=/boot install'
53 # executable name for each wm/de used in ~/.xinitrc {
54 declare -A WM_SESSIONS=(
55 [dwm]='dwm' [i3-gaps]='i3' [bspwm]='bspwm' [awesome]='awesome' [plasma]='startkde' [xfce4]='startxfce4'
56 [gnome]='gnome-session' [fluxbox]='startfluxbox' [openbox]='openbox-session' [cinnamon]='cinnamon-session'
59 # packages installed for each wm/de, most are depends of the skel packages {
61 [dwm]='' [gnome]='' [cinnamon]='gnome-terminal' [plasma]='kdebase-meta'
62 [awesome]='archlabs-skel-awesome' [bspwm]='archlabs-skel-bspwm' [fluxbox]='archlabs-skel-fluxbox'
63 [i3-gaps]='archlabs-skel-i3-gaps' [openbox]='archlabs-skel-openbox' [xfce4]='archlabs-skel-xfce4 xfce4-goodies'
66 # files offered for editing after install is complete {
67 declare -A EDIT_FILES=(
68 [login]='' # login is populated once we know the username and shell
69 [fstab]='/etc/fstab' [sudoers]='/etc/sudoers' [crypttab]='/etc/crypttab' [pacman]='/etc/pacman.conf'
70 [console]='/etc/vconsole.conf' [mkinitcpio]='/etc/mkinitcpio.conf' [hostname]='/etc/hostname /etc/hosts'
71 [bootloader]="/boot/loader/entries/$DIST.conf" # ** based on bootloader
72 [locale]='/etc/locale.conf /etc/default/locale' [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
75 # mkfs command flags for filesystem formatting {
76 declare -A FS_CMD_FLAGS=(
77 [f2fs]='' [jfs]='-q' [xfs]='-f' [ntfs]='-q' [ext2]='-q' [ext3]='-q' [ext4]='-q' [vfat]='-F32' [nilfs2]='-q' [reiserfs]='-q'
80 # mount options for each filesystem {
82 [vfat]='' [ntfs]='' [ext2]='' [ext3]='' # NA
83 [jfs]='discard errors=continue errors=panic nointegrity'
84 [reiserfs]='acl nolog notail replayonly user_xattr off'
85 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
86 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
87 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
88 [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'
91 # packages installed for each login option {
92 declare -A LOGIN_PKGS=(
93 [xinit]='xorg-xinit' [ly]='archlabs-ly' [gdm]='gdm' [sddm]='sddm'
94 [lightdm]='lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice'
97 # extras installed for user selected packages {
98 # if a package requires additional packages that aren't already dependencies
99 # they can be added here eg. [package]="extra"
101 [vlc]='qt4' [mpd]='mpc' [mupdf]='mupdf-tools'
102 [rxvt-unicode]='urxvt-pearls' [zathura]='zathura-pdf-poppler' [noto-fonts]='noto-fonts-emoji' [cairo-dock]='cairo-dock-plug-ins' [qt5ct]='qt5-styleplugins'
103 [vlc]='qt5ct qt5-styleplugins' [qutebrowser]='qt5ct qt5-styleplugins' [qbittorrent]='qt5ct qt5-styleplugins' [transmission-qt]='qt5ct qt5-styleplugins'
104 [bluez]='bluez-libs bluez-utils bluez-tools bluez-plugins bluez-hid2hci' [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
107 # dialog text variables {
108 # Basics (somewhat in order)
109 _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"
110 _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"
111 _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"
112 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
113 _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."
114 _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."
115 _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"
116 _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)."
117 _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."
118 _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."
119 _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."
120 _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"
121 _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."
122 _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."
123 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
124 _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."
125 _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."
126 _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"
127 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
128 _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."
129 _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."
130 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
131 _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"
132 _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."
133 _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."
136 _luksnew="Basic LUKS Encryption"
137 _luksadv="Advanced LUKS Encryption"
138 _luksopen="Open Existing LUKS Partition"
139 _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."
140 _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."
141 _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)."
144 _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."
145 _lvmnew="Create Volume Group and Volume(s)"
146 _lvmdel="Delete an Existing Volume Group"
147 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
148 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
149 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
150 _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."
151 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
154 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
155 _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"
156 _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"
157 _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"
158 _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"
159 _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"
160 _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"
164 ###############################################################################
166 # main is the entry point which calls functions including outside of its block
167 # once those functions finished they always are returned here with the
168 # exception of install_main(), it exits upon completion
172 (( SEL < 12 )) && (( SEL++ ))
174 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
175 1 "Device tree (optional)" \
176 2 "Partitioning (optional)" \
177 3 "LUKS setup (optional)" \
178 4 "LVM setup (optional)" \
179 5 "Mount partitions" \
180 6 "System bootloader" \
181 7 "User and password" \
182 8 "System configuration" \
183 9 "Select WM/DE (optional)" \
184 10 "Select Packages (optional)" \
185 11 "View configuration (optional)" \
186 12 "Start the installation" 2>"$ANS"
189 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
192 2) part_menu || (( SEL-- )) ;;
193 3) luks_menu || (( SEL-- )) ;;
194 4) lvm_menu || (( SEL-- )) ;;
195 5) mount_menu || (( SEL-- )) ;;
196 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
197 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
198 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
199 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
200 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
201 11) prechecks 3 && select_show ;;
202 12) prechecks 3 && install_main ;;
203 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
209 if [[ $SYS == 'BIOS' ]]; then
210 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
211 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
212 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
214 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
215 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
216 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
217 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
218 "efistub" "Boot the kernel image directly (no chainloading support)" \
219 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
226 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
227 [[ $BOOT_PART ]] && local mnt="/$BOOTDIR"
228 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
229 pkgs="${pkgs// / }" pkgs="${pkgs# }"
230 msg "Show Configuration" "
231 ---------- PARTITION CONFIGURATION ------------
233 Root: ${ROOT_PART:-none}
234 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
236 Swap: ${SWAP_PART:-none}
237 Size: ${SWAP_SIZE:-none}
238 Extra: ${EXMNTS:-${EXMNT:-none}}
239 Hooks: ${HOOKS:-none}
245 ------------ SYSTEM CONFIGURATION -------------
247 Locale: ${MYLOCALE:-none}
248 Keymap: ${KEYMAP:-none}
249 Hostname: ${MYHOST:-none}
250 Timezone: ${ZONE:-none}/${SUBZ:-none}
253 ------------ USER CONFIGURATION ---------------
255 Username: ${NEWUSER:-none}
256 Login Shell: ${MYSHELL:-none}
257 Login Session: ${LOGIN_WM:-none}
258 Autologin: ${AUTOLOGIN:-none}
259 Login Type: ${LOGIN_TYPE:-none}
262 ----------- PACKAGE CONFIGURATION -------------
264 Kernel: ${KERNEL:-none}
265 Bootloader: ${BOOTLDR:-none}
266 Packages: ${pkgs:-none}
272 [[ $INSTALL_WMS ]] || return 0
274 AUTOLOGIN='' # no autologin unless using xinit
276 dlg LOGIN_TYPE menu "Login Management" "\nSelect what kind of login management to use." \
277 "xinit" "Console login without a display manager" \
278 "ly" "TUI display manager with a ncurses-like interface" \
279 "lightdm" "Lightweight display manager with a gtk greeter" \
280 "gdm" "Gnome display manager" \
281 "sddm" "Simple desktop display manager" || return 1
284 ly) EDIT_FILES[login]="/etc/ly/config.ini" ;;
285 gdm|sddm) EDIT_FILES[login]="" ;;
286 lightdm) EDIT_FILES[login]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf" ;;
287 xinit) EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
288 if (( $(wc -w <<< "$INSTALL_WMS") > 1 )); then
289 dlg LOGIN_WM menu "Login Management" "$_login" $LOGIN_CHOICES || return 1
290 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
292 [[ -z $LOGIN_WM ]] && LOGIN_WM="${WM_SESSIONS[${INSTALL_WMS%% *}]}"
293 yesno "Autologin" "$(sed "s|USER|$NEWUSER|g; s|RC|$LOGINRC|g" <<< "$_autologin")" && AUTOLOGIN=true || AUTOLOGIN=''
303 until [[ $CONFIG_DONE ]]; do
305 0) dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
306 zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
307 bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
308 mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
310 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
311 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
313 until [[ $ZONE && $SUBZ ]]; do
314 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
315 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
317 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
318 4) dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
319 linux 'Vanilla linux kernel and modules, with a few patches applied' \
320 linux-lts 'Long-term support (LTS) linux kernel and modules' \
321 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
322 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
326 (( i++ )) # progress through to the next choice
330 bash) LOGINRC='.bash_profile' ;;
331 zsh) LOGINRC='.zprofile' ;;
332 mksh) LOGINRC='.profile' ;;
343 until [[ $NEWUSER ]]; do
345 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
346 "Username:" 1 1 "${ans[0]}" 1 11 "$COLUMNS" 0 0 \
347 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
348 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
349 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
350 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
351 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
353 mapfile -t ans <"$ANS"
355 # root passwords empty, so use the user passwords
356 if [[ -z "${ans[4]}" && -z "${ans[5]}" ]]; then
361 # make sure a username was entered and that the passwords match
362 if [[ -z ${ans[0]} || ${ans[0]} =~ \ |\' || ${ans[0]} =~ [^a-z0-9] ]]; then
363 msg "Invalid Username" "\nInvalid user name.\n\nPlease try again.\n"; u=''
364 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
365 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
366 elif [[ "${ans[4]}" != "${ans[5]}" ]]; then
367 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
370 USER_PASS="${ans[1]}"
371 ROOT_PASS="${ans[4]}"
379 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
380 us English cm English gb English au English gh English \
381 za English ng English ca French 'cd' French gn French \
382 tg French fr French de German at German ch German \
383 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
384 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
385 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
386 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
387 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
388 dk Danish be Belgian in Indian al Albanian am Armenian \
389 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
390 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
391 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
392 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
393 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
394 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
395 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
396 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
397 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
398 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
399 me Montenegrin || return 1
401 if [[ $CMAPS == *"$KEYMAP"* ]]; then
404 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
407 if [[ $TERM == 'linux' ]]; then
408 loadkeys "$CMAP" >/dev/null 2>&1
410 setxkbmap "$KEYMAP" >/dev/null 2>&1
419 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
420 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
421 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
422 dwm "A dynamic WM for X that manages windows in tiled, floating, or monocle layouts" "$(ofn dwm "${INSTALL_WMS[*]}")" \
423 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
424 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" \
425 awesome "A customized Awesome WM session created by @elanapan" "$(ofn awesome "${INSTALL_WMS[*]}")" \
426 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
427 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
428 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
429 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")"
431 [[ $INSTALL_WMS ]] || return 0
433 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
434 WM_PKGS="${WM_PKGS// / }" # remove double spaces
435 WM_PKGS="${WM_PKGS# }" # remove leading space
437 for i in $INSTALL_WMS; do
438 LOGIN_CHOICES+="$i - "
439 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
442 select_login || return 1
444 while IFS=' ' read -r pkg; do
445 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
453 dlg USER_PKGS check " Packages " "$_packages" \
454 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
455 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
456 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
457 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
458 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
459 blueman "GUI bluetooth device manager" "$(ofn blueman "${USER_PKGS[*]}")" \
460 bluez "Simple CLI based bluetooth support" "$(ofn bluez "${USER_PKGS[*]}")" \
461 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
462 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
463 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
464 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
465 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
466 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
467 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
468 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
469 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
470 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
471 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
472 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
473 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
474 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
475 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
476 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
477 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
478 gnome-calculator "GNOME Scientific calculator" "$(ofn gnome-calculator "${USER_PKGS[*]}")" \
479 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
480 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
481 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
482 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
483 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
484 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
485 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
486 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
487 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
488 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
489 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
490 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
491 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
492 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
493 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
494 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
495 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
496 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
497 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
498 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
499 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
500 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
501 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
502 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
503 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
504 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
505 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
506 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
507 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
508 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
509 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
510 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
511 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
512 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
513 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
514 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
515 simple-scan "Simple scanning utility" "$(ofn simple-scan "${USER_PKGS[*]}")" \
516 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
517 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
518 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
519 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
520 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
521 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
522 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
523 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
524 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
525 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
526 transmission-gtk "GTK+ Front end for transmission" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
527 transmission-qt "Qt Front end for transmission" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
528 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
529 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
530 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
531 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
532 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
533 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
534 xapps "Common library for X-Apps project" "$(ofn xapps "${USER_PKGS[*]}")" \
535 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
536 xed "A small and lightweight text editor. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
537 xfce4-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce4-terminal "${USER_PKGS[*]}")" \
538 xreader "Document viewer for files like PDF and Postscript. X-Apps Project." "$(ofn xed "${USER_PKGS[*]}")" \
539 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
540 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
542 if [[ $USER_PKGS ]]; then # add any needed PKG_EXT to the list
543 for i in $USER_PKGS; do
544 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
551 ###############################################################################
553 # non-essential partitioning helpers called by the user when using the optional
554 # partition menu and selecting a device to edit
558 no_bg_install || return 0
559 local device choice devhash
560 devhash="$(lsblk -f | base64)"
562 part_device || return 1
567 dlg choice menu "Edit Partitions" "$_part\n\n$(lsblk -no NAME,MODEL,SIZE,TYPE,FSTYPE $device)" \
568 "auto" "Whole device automatic partitioning" \
569 "shrink" "Shrink an existing ext or ntfs partition" \
570 "cfdisk" "Curses based variant of fdisk" \
571 "parted" "GNU partition editor" \
572 "fdisk" "Dialog-driven creation and manipulation of partitions" \
573 "done" "Return to the main menu"
575 if [[ -z $choice || $choice == 'done' ]]; then
577 elif [[ $choice == 'shrink' ]]; then
578 part_shrink "$device"
579 elif [[ $choice == 'auto' ]]; then
580 local root_size txt table boot_fs
581 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
584 print ($1 * 1000 - 512) / 1000 "G"
590 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
591 if [[ $SYS == 'BIOS' ]]; then
592 table="msdos" boot_fs="ext4"
593 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
595 table="gpt" boot_fs="fat32"
596 txt+="A $boot_fs efi boot partition (512M)\n- "
598 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
599 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
605 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
606 msg "Probing Partitions" "\nInforming kernel of partition changes using partprobe\n" 0
607 partprobe >/dev/null 2>&1
608 [[ $choice == 'auto' ]] && return
616 if [[ $IGNORE_DEV ]]; then
617 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
619 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
621 msg "Device Tree" "\n\n$txt\n\n"
626 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
627 dev_info="$(parted -s "$device" print)"
629 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
632 while read -r PART; do
633 parted -s "$device" rm "$PART" >/dev/null 2>&1
634 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
636 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
638 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
639 if [[ $SYS == "BIOS" ]]; then
640 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
642 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
647 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
649 if [[ $SYS == "BIOS" ]]; then
650 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
652 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
655 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
656 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
658 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
659 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
661 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
668 local device="$1" fs=""
670 part_find "${device##*/}[^ ]" || return 1
671 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
673 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS; then
674 fs=$(lsblk -lno FSTYPE "$part")
677 msg "Resize" "\nGathering device size info.\n" 0
679 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print $3}') # part size in KiB
680 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print $3}') # whole device size in KiB
681 mount "$part" $MNT >/dev/null 2>&1; sleep 0.5
682 min=$(df --output=used --block-size=MiB "$part" | awk 'NR == 2 {print int($1) + 256}')
683 max=$(df --output=avail --block-size=MiB "$part" | awk 'NR == 2 {print int($1)}')
686 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$min" "$max" $((max / 2)) 2>$ANS; then
688 size=$((size * 1024))
695 if ntfsresize -fc "$part"; then
696 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
697 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
699 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"
704 e2fsck -f "$part"; sleep 0.5
705 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
706 errshow "resize2fs -f $part ${size}K" || return 1
710 parted "$device" resizepart "$num" ${size}KiB || return 1
713 if [[ $devsize == "$end" ]]; then
714 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
715 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
717 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
718 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
720 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n" 1
722 "") msg "No Filesystem" "\nFor unformatted partitions, cfdisk can be used in the partition menu.\n" ;;
723 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n" ;;
728 ###############################################################################
729 # partition management functions
730 # these are helpers for use by other functions to do essential setup/teardown
734 local regexp="$1" err=''
736 # string of partitions as /TYPE/PART SIZE
737 if [[ $IGNORE_DEV ]]; then
738 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
739 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
740 sub(/^part/, "/dev/")
741 sub(/^lvm|^crypt/, "/dev/mapper/")
745 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
747 sub(/^part/, "/dev/")
748 sub(/^lvm|^crypt/, "/dev/mapper/")
753 # number of partitions total
755 while read -r line; do
759 # ensure we have enough partitions for the system and action type
761 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
762 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
763 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
766 # if there aren't enough partitions show the relevant error message
767 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
774 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
775 fallocate -l $SWAP_SIZE "$1" 2>$ERR
776 errshow "fallocate -l $SWAP_SIZE $1"
777 chmod 600 "$1" 2>$ERR
778 errshow "chmod 600 $1"
780 mkswap "$1" >/dev/null 2>$ERR
782 swapon "$1" >/dev/null 2>$ERR
789 local part="$1" mountp="${MNT}$2" fs=""
790 fs="$(lsblk -lno FSTYPE "$part")"
793 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" && $part != "$AUTO_ROOT_PART" ]] && select_mntopts "$fs"; then
794 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
796 mount "$part" "$mountp" >/dev/null 2>&1
799 part_mountconf "$part" "$mountp" || return 1
807 local part="$1" fs="$2" delay="$3"
809 msg "Format" "\nFormatting $part as $fs\n" 0
810 mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part" >/dev/null 2>$ERR
811 errshow "mkfs.$fs ${FS_CMD_FLAGS[$fs]} "$part"" || return 1
818 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
819 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
820 elif (( DEV_COUNT > 1 )); then
822 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
824 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
826 [[ $DEVICE ]] || return 1
827 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
828 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2
832 [[ $1 ]] && BOOT_DEV="$DEVICE"
839 BOOT_DEV="${BOOT_PART%[1-9]}"
840 BOOT_PART_NUM="${BOOT_PART: -1}"
841 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
842 if [[ $SYS == 'UEFI' ]]; then
843 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
845 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
852 local part="$1" devs=""
853 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
855 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
856 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
858 LUKS_NAME="${part#/dev/mapper/}"
859 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
860 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
861 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
866 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
867 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
868 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
869 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
873 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
875 VNAME="${part#/dev/mapper/}"
876 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
877 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
878 LUKS_NAME="${dev/\/dev\/mapper\//}"
882 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
883 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
884 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
885 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
896 if (( COUNT > 0 )); then
897 PARTS="$(sed "/${pt//\//\\/}/d" <<< "$PARTS")"
905 if grep -qw "$1" /proc/mounts; then
906 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
910 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
915 ###############################################################################
917 # mount_menu is the entry point which calls all other functions
918 # once finished it returns to the main menu: main()
922 msg "Info" "\nGathering device info.\n" 0
923 no_bg_install || return 0
926 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
928 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
929 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
931 select_root_partition || return 1
933 if [[ $SYS == 'UEFI' ]]; then
934 select_efi_partition || { BOOT_PART=''; return 1; }
935 elif (( COUNT > 0 )); then
936 select_boot_partition || { BOOT_PART=''; return 1; }
939 if [[ $BOOT_PART ]]; then
940 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
944 select_swap || return 1
945 select_extra_partitions || return 1
953 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
954 "none" "Don't allocate any swap space" \
955 "swapfile" "Allocate $SYS_MEM at /swapfile" \
958 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
961 elif [[ $SWAP_PART == "swapfile" ]]; then
963 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
964 (( i > 0 )) && msg "Swap Size Error" "\nSwap size must be 1(M|G) or greater, and can only contain whole numbers\n\nSize entered: $SWAP_SIZE\n" 2
965 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
968 part_swap "$MNT/$SWAP_PART"
969 SWAP_PART="/$SWAP_PART"
970 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
972 part_countdec $SWAP_PART
973 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
983 local fs="$1" opts=''
984 local title="${fs^} Mount Options"
986 for i in ${FS_OPTS[$fs]}; do
990 until [[ $MNT_OPTS ]]; do
991 dlg MNT_OPTS check "$title" "$_mount" $opts
992 [[ $MNT_OPTS ]] || return 1
993 MNT_OPTS="${MNT_OPTS// /,}"
994 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1003 until [[ $EXMNT ]]; do
1004 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1005 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1006 msg "Mountpoint Error" "$_errexpart"
1015 local part="$1" fs='' cur=''
1016 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1017 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1019 # bail early if the partition was created in part_auto()
1020 [[ $cur && $part == "$AUTO_ROOT_PART" ]] && return 0
1023 if [[ $cur && $FORMATTED == *"$part"* ]]; then
1024 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1026 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1028 [[ $fs == 'skip' ]] && return 0
1029 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1031 part_format "$part" "$fs"
1034 select_efi_partition()
1036 if [[ $AUTO_BOOT_PART ]]; then
1037 BOOT_PART="$AUTO_BOOT_PART"
1038 return 0 # were done here
1040 local pts size dev isize bsize ptcount=0
1042 # walk partition list and skip ones that are too small/big for boot
1043 while read -r dev size; do
1044 size_t="${size: -1:1}" # size type eg. K, M, G, T
1045 isize=${size:0:-1} # remove trailing size type character
1046 isize=${isize%.*} # remove any decimal (round down)
1047 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1050 if (( ptcount == 1 )); then
1051 msg "EFI Boot Partition" "\nOnly one partition available that meets size requirements.\n" 1
1052 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1054 dlg BOOT_PART menu "EFI Partition" "$_uefi" $pts
1058 if [[ -z $BOOT_PART ]]; then
1060 elif grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1061 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1062 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1063 part_format "$BOOT_PART" "vfat" 2
1066 part_format "$BOOT_PART" "vfat" 2
1072 select_boot_partition()
1074 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1075 BOOT_PART="$AUTO_BOOT_PART"
1076 return 0 # were done here
1078 local pts size dev isize bsize ptcount=0
1080 # walk partition list and skip ones that are too small/big for boot
1081 while read -r dev size; do
1082 size_t="${size: -1:1}" # size type eg. K, M, G, T
1083 isize=${size:0:-1} # remove trailing size type character
1084 isize=${isize%.*} # remove any decimal (round down)
1085 [[ $size_t =~ [KT] || ($size_t == 'G' && $isize -gt 2) || ($size_t == 'M' && $isize -lt 100) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1088 if [[ $LUKS && ! $LVM ]]; then
1089 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $pts
1090 [[ $BOOT_PART ]] || return 1
1092 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $pts
1093 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1097 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1098 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1099 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1100 part_format "$BOOT_PART" "ext4" 2
1103 part_format "$BOOT_PART" "ext4" 2
1108 select_root_partition()
1110 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1111 ROOT_PART="$AUTO_ROOT_PART"
1112 msg "Mount Menu" "\nUsing partitions created during automatic format.\n" 2
1113 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1114 return 0 # we're done here
1116 local pts size dev isize bsize ptcount=0
1118 # walk partition list and skip ones that are too small for / (root)
1119 while read -r dev size; do
1120 size_t="${size: -1:1}" # size type eg. K, M, G, T
1121 isize=${size:0:-1} # remove trailing size type character
1122 isize=${isize%.*} # remove any decimal (round down)
1123 [[ $size_t =~ [MK] || ($size_t == 'G' && $isize -lt 4) ]] || { pts+="$dev $size "; (( ptcount++ )); }
1126 if (( ptcount == 1 )); then # only one available device
1127 msg "Root Partition (/)" "\nOnly one partition available that meets size requirements.\n" 2
1128 ROOT_PART="$(awk 'NF > 0 {print $1}' <<< "$pts")"
1130 dlg ROOT_PART menu "Mount Root" "\nSelect the root (/) partition, this is where $DIST will be installed.\n\nDevices smaller than 8G will not be shown here." $pts
1134 if [[ -z $ROOT_PART ]] || ! select_filesystem "$ROOT_PART" || ! part_mount "$ROOT_PART"; then
1142 select_extra_partitions()
1146 # walk partition list and skip ones that are too small to be usable
1147 while read -r dev size; do
1148 [[ ${size: -1:1} =~ [KM] ]] && part_countdec "$dev"
1151 while (( COUNT > 0 )); do
1153 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1154 if [[ $part == 'done' ]]; then
1156 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1157 EXMNTS+="$part: $EXMNT "
1158 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1166 ###############################################################################
1168 # main is the entry point which calls all other install functions, once
1169 # complete it shows a dialog to edit files on the new system before reboot
1174 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1175 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1176 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1180 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1183 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1186 dlg choice menu "Finalization" "$_edit" \
1187 finished "exit the installer and reboot" \
1188 keyboard "${EDIT_FILES[keyboard]}" \
1189 console "${EDIT_FILES[console]}" \
1190 locale "${EDIT_FILES[locale]}" \
1191 hostname "${EDIT_FILES[hostname]}" \
1192 sudoers "${EDIT_FILES[sudoers]}" \
1193 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1194 fstab "${EDIT_FILES[fstab]}" \
1195 crypttab "${EDIT_FILES[crypttab]}" \
1196 bootloader "${EDIT_FILES[bootloader]}" \
1197 pacman "${EDIT_FILES[pacman]}" \
1198 login "${EDIT_FILES[login]}"
1200 if [[ -z $choice || $choice == 'finished' ]]; then
1201 [[ $DEBUG == true && -r $DBG ]] && ${EDITOR:-vim} $DBG
1205 for f in ${EDIT_FILES[$choice]}; do
1206 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1208 if [[ $exists ]]; then
1209 ${EDITOR:-vim} -O $exists
1211 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1221 while kill -0 $BG_PID 2>/dev/null; do
1222 clear; printf "\nA background install process is still running...\n"; sleep 1
1227 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1228 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1229 sed -i 's/#\(Storage=\)volatile/\1auto/' $MNT/etc/systemd/journald.conf
1230 find $MNT/boot -name '*-ucode.img' -delete
1232 [[ $DIST != "ArchLabs" ]] || sed -i "s/ArchLabs/$DIST/g" $MNT/etc/{lsb-release,os-release}
1235 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1236 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1237 echo "Creating Intel VGA Tear Free config /etc/X11/xorg.conf.d/20-intel.conf"
1238 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf <<- EOF
1240 Identifier "Intel Graphics"
1242 Option "TearFree" "true"
1247 [[ -e /run/archiso/sfs/airootfs ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1248 [[ -d /etc/netctl ]] && cp -rfv /etc/netctl $MNT/etc/
1249 [[ -f /etc/resolv.conf ]] && cp -fv /etc/resolv.conf $MNT/etc/
1250 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1252 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1253 cp -fv $MNT/etc/locale.conf $MNT/etc/default/locale
1254 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1256 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1258 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf <<- EOF
1259 # Use localectl(1) to instruct systemd-localed to update it.
1260 Section "InputClass"
1261 Identifier "system-keyboard"
1262 MatchIsKeyboard "on"
1263 Option "XkbLayout" "$KEYMAP"
1267 cat > $MNT/etc/default/keyboard <<- EOF
1268 # KEYBOARD CONFIGURATION FILE
1269 # Consult the keyboard(5) manual page.
1276 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1277 echo "$MYHOST" > $MNT/etc/hostname
1278 cat > $MNT/etc/hosts <<- EOF
1281 ::1 localhost ip6-localhost ip6-loopback
1282 ff02::1 ip6-allnodes
1283 ff02::2 ip6-allrouters
1289 echo "Installing $BOOTLDR"
1291 if [[ $ROOT_PART == /dev/mapper* ]]; then
1292 ROOT_PART_ID="$ROOT_PART"
1294 local uuid_type="UUID"
1295 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1296 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1299 if [[ $SYS == 'UEFI' ]]; then
1300 # remove our old install and generic BOOT/ dir
1301 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1302 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'BOOT' -type d -delete
1306 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1307 errshow 1 "${BCMDS[$BOOTLDR]}"
1309 if [[ -d $MNT/hostrun ]]; then
1310 # cleanup the bind mounts we made earlier for the grub-probe module
1311 umount_dir $MNT/hostrun/{udev,lvm}
1312 rm -rf $MNT/hostrun >/dev/null 2>&1
1315 if [[ $SYS == 'UEFI' ]]; then
1316 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1317 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1319 grub) cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1320 syslinux) cp -rf "$MNT/$BOOTDIR/EFI/syslinux/"* $MNT/$BOOTDIR/EFI/BOOT/ && cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1321 refind-efi) sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1322 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI ;;
1331 rm -f $MNT/root/.zshrc # remove welcome message from root zshrc
1333 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1334 errshow 1 "set root password"
1335 if [[ $MYSHELL != 'zsh' ]]; then # root uses zsh by default
1336 chrun "usermod -s /bin/$MYSHELL root" 2>$ERR
1337 errshow 1 "usermod -s /bin/$MYSHELL root"
1338 # copy the default mkshrc to /root if it was selected
1339 [[ $MYSHELL == 'mksh' ]] && cp -fv $MNT/etc/skel/.mkshrc $MNT/root/.mkshrc
1342 echo "Creating new user $NEWUSER and setting password"
1343 local groups='audio,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1345 chrun "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER" 2>$ERR
1346 errshow 1 "useradd -m -u 1000 -g users -G $groups -s /bin/$MYSHELL $NEWUSER"
1347 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1348 errshow 1 "set $NEWUSER password"
1350 if [[ $INSTALL_WMS == *dwm* ]];then
1351 mkdir -pv "$MNT/home/$NEWUSER/suckless"
1352 for i in dwm dmenu st; do
1353 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1354 chrun "cd /home/$NEWUSER/suckless/$i; make prefix=/usr install; make clean"
1356 printf "failed to clone %s repo\n" "$i"
1361 [[ $MYSHELL != 'bash' ]] && rm -rf "$MNT/home/$NEWUSER/.bash"*
1362 [[ $MYSHELL != 'zsh' ]] && rm -rf "$MNT/home/$NEWUSER/.z"*
1364 # remove some commands from ~/.xprofile when using KDE or Gnome as the login session
1365 if [[ $LOGIN_WM =~ (startkde|gnome-session) || ($LOGIN_TYPE != 'xinit' && $WM_PKGS =~ (plasma|gnome)) ]]; then
1366 sed -i '/super/d; /nitrogen/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile"
1367 elif [[ $LOGIN_WM == 'dwm' ]]; then # and dwm
1368 sed -i '/super/d; /compton/d' "$MNT/home/$NEWUSER/.xprofile" "$MNT/root/.xprofile"
1371 # create user home directories (Music, Documents, Downloads, etc..)
1372 chrun 'xdg-user-dirs-update'
1379 local serv="$MNT/etc/systemd/system/getty@tty1.service.d"
1380 echo "Setting up $LOGIN_TYPE"
1382 ly|sddm|gdm|lightdm)
1383 if [[ $LOGIN_WM == *dwm* ]]; then # dwm doesn't include an xsession file for display managers
1384 mkdir -p $MNT/usr/share/xsessions
1385 cat >$MNT/usr/share/xsessions/dwm.desktop <<- EOF
1389 Comment=Dynamic Window Manager
1394 rm -rf "$serv" "$MNT/home/$NEWUSER/.xinitrc"
1395 chrun "systemctl enable $LOGIN_TYPE.service" 2>$ERR
1396 errshow 1 "systemctl enable $LOGIN_TYPE.service"
1397 ${LOGIN_TYPE}_config
1400 if [[ $INSTALL_WMS ]]; then
1401 sed -i "/exec/ c exec ${LOGIN_WM}" "$MNT/home/$NEWUSER/.xinitrc"
1402 elif [[ -e $MNT/home/$NEWUSER/.xinitrc ]]; then
1403 sed -i '/exec/d' "$MNT/home/$NEWUSER/.xinitrc"
1406 if [[ $AUTOLOGIN ]]; then
1407 sed -i "s/root/${NEWUSER}/g" $serv/autologin.conf
1408 cat > "$MNT/home/$NEWUSER/$LOGINRC" <<- EOF
1409 # automatically run startx when logging in on tty1
1410 [ -z "\$DISPLAY" ] && [ \$XDG_VTNR -eq 1 ] && startx
1421 local rmpkg="archlabs-installer "
1422 local inpkg="$PACKAGES $USER_PKGS $AL_BASE_PKGS "
1424 if [[ $MYSHELL == 'zsh' ]]; then
1425 inpkg+="zsh-completions "
1430 if [[ $INSTALL_WMS == 'dwm' ]]; then # dwm only needs a very limited package set
1431 inpkg+="nitrogen polkit-gnome gnome-keyring dunst "
1433 [[ $INSTALL_WMS =~ (plasma|gnome|cinnamon) ]] || inpkg+="archlabs-ksuperkey "
1434 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|fluxbox) ]] && inpkg+="$WM_BASE_PKGS "
1435 [[ $inpkg =~ (term|plasma|rxvt|tilda|tilix|sakura) || $INSTALL_WMS =~ (gnome|plasma|xfce4) ]] || inpkg+="xterm "
1438 # update and install crucial packages first to avoid issues
1439 chrun "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed" 2>$ERR
1440 errshow 1 "pacman -Syyu $KERNEL $BASE_PKGS ${LOGIN_PKGS[$LOGIN_TYPE]} $MYSHELL --noconfirm --needed"
1442 # remove the packages we don't want on the installed system
1443 chrun "pacman -Rnsc $rmpkg --noconfirm"
1445 # reinstalling iputils fixes the network issue for non-root users
1446 chrun "pacman -S iputils $UCODE --noconfirm"
1448 # install the packages chosen throughout the install
1449 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1450 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1452 # bootloader packages
1453 if [[ $BOOTLDR == 'grub' ]]; then
1454 [[ $SYS == 'UEFI' ]] && local efib="efibootmgr"
1455 chrun "pacman -S os-prober grub $efib --needed --noconfirm" 2>$ERR
1456 errshow 1 "pacman -S os-prober grub $efib --needed --noconfirm"
1457 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1458 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1459 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1460 elif [[ $SYS == 'UEFI' ]]; then
1461 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1462 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1465 # allow members of the wheel group to run commands as root
1466 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1471 install_mkinitcpio()
1474 [[ $LUKS ]] && add="encrypt"
1475 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1476 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1477 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1478 errshow 1 "mkinitcpio -p $KERNEL"
1481 install_mirrorlist()
1483 if hash reflector >/dev/null 2>&1; then
1484 reflector --verbose --score 80 -l 40 -f 5 --sort rate --save "$1"
1485 elif hash rankmirrors >/dev/null 2>&1; then
1486 echo "Sorting mirrorlist"
1487 local key="access_key=5f29642060ab983b31fdf4c2935d8c56"
1488 ip_add="$(curl -fsSL "http://api.ipstack.com/check&?$key&fields=ip" | python -c "import sys, json; print(json.load(sys.stdin)['ip'])")"
1489 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'])")"
1490 if [[ "$country" ]]; then
1491 if [[ $country =~ (CA|US) ]]; then
1492 # use both CA and US mirrors for CA or US countries
1493 mirror="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1494 elif [[ $country =~ (AU|NZ) ]]; then
1495 # use both AU and NZ mirrors for AU or NZ countries
1496 mirror="https://www.archlinux.org/mirrorlist/?country=AU&country=NZ&use_mirror_status=on"
1498 mirror="https://www.archlinux.org/mirrorlist/?country=${country}&use_mirror_status=on"
1500 else # no country code so just grab all mirrors, will be a very slow sort but we don't have other options
1501 mirror="https://www.archlinux.org/mirrorlist/?country=all&use_mirror_status=on"
1503 curl -fsSL "$mirror" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 6 - >"$1"
1509 install_background()
1511 ( rsync -a /run/archiso/sfs/airootfs/ $MNT/ && install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" >/dev/null 2>&1 ) &
1513 trap "kill $BG_PID 2>/dev/null" EXIT
1516 ###############################################################################
1517 # display manager config
1518 # these are called based on which DM is chosen after it is installed
1519 # additional config can be handled here, for now only lightdm has one
1523 cat > $MNT/etc/lightdm/lightdm-gtk-greeter.conf <<- EOF
1525 default-user-image=/usr/share/icons/ArchLabs-Dark/64x64/places/distributor-logo-archlabs.png
1526 background=/usr/share/backgrounds/archlabs/archlabs.jpg
1527 theme-name=Adwaita-dark
1528 icon-theme-name=Adwaita
1529 font-name=DejaVu Sans Mono 11
1530 position=30%,end 50%,end
1549 ###############################################################################
1551 # prerun_* set up the configs needed before actually running the commands
1552 # setup_* are run after selecting a bootloader and build the command used later
1553 # they can also be used for further user input as these run before control is taken away
1557 EDIT_FILES[bootloader]="/etc/default/grub"
1559 if [[ $SYS == 'BIOS' ]]; then
1560 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1561 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1563 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1564 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1565 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1568 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1569 mount --bind /hostrun/udev /run/udev &&
1570 mount --bind /hostrun/lvm /run/lvm &&
1572 grub-mkconfig -o /boot/grub/grub.cfg &&
1573 sleep 1 && umount /run/udev /run/lvm"
1580 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1582 if [[ $LUKS_DEV ]]; then
1583 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
1584 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"
1587 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1588 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1589 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1592 # setup for os-prober module
1593 mkdir -p /run/{lvm,udev} $MNT/hostrun/{lvm,udev}
1594 mount --bind /run/lvm $MNT/hostrun/lvm
1595 mount --bind /run/udev $MNT/hostrun/udev
1602 EDIT_FILES[bootloader]=""
1607 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1608 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1609 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1614 if [[ $SYS == 'BIOS' ]]; then
1615 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1617 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1618 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1619 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1625 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1626 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64"; d=''; }
1629 cp -rfv "$s/"* "$c/"
1630 cat > "$c/syslinux.cfg" <<- EOF
1633 MENU TITLE $DIST Boot Menu
1638 MENU LABEL $DIST Linux
1639 LINUX $d/vmlinuz-$KERNEL
1640 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1641 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1643 LABEL ${DIST}fallback
1644 MENU LABEL $DIST Linux Fallback
1645 LINUX $d/vmlinuz-$KERNEL
1646 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1647 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1654 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1655 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; refind-install"
1660 cat > $MNT/boot/refind_linux.conf <<- EOF
1661 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1662 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1663 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1664 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1665 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1666 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1668 mkdir -p $MNT/etc/pacman.d/hooks
1669 cat > $MNT/etc/pacman.d/hooks/refind.hook <<- EOF
1676 Description = Updating rEFInd on ESP
1677 When = PostTransaction
1678 Exec = /usr/bin/refind-install
1682 setup_systemd-boot()
1684 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1685 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1; bootctl --path=/boot install"
1688 prerun_systemd-boot()
1690 mkdir -p $MNT/boot/loader/entries
1691 cat > $MNT/boot/loader/loader.conf <<- EOF
1696 cat > $MNT/boot/loader/entries/$DIST.conf <<- EOF
1698 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1699 initrd /initramfs-$KERNEL.img
1700 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1702 cat > $MNT/boot/loader/entries/$DIST-fallback.conf <<- EOF
1703 title $DIST Linux Fallback
1704 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1705 initrd /initramfs-$KERNEL-fallback.img
1706 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1708 mkdir -p $MNT/etc/pacman.d/hooks
1709 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook <<- EOF
1716 Description = Updating systemd-boot
1717 When = PostTransaction
1718 Exec = /usr/bin/bootctl update
1720 systemd-machine-id-setup --root="$MNT"
1724 ###############################################################################
1729 msg "Info" "\nGathering device info.\n" 0
1730 no_bg_install || return 1
1734 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1735 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1736 "$_lvmdel" "vgremove -f" \
1737 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1738 "Back" "Return to the main menu"
1740 "$_lvmnew") lvm_create && break ;;
1741 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1742 "$_lvmdelall") lvm_del_all ;;
1753 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1754 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1755 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1757 if [[ $VGROUP && $v && $pv ]]; then
1758 msg "LVM Setup" "\nActivating existing logical volume management.\n" 0
1759 modprobe dm-mod >/dev/null 2>$ERR
1760 errshow 'modprobe dm-mod'
1761 vgscan >/dev/null 2>&1
1762 vgchange -ay >/dev/null 2>&1
1768 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1770 lvm_mkgroup || return 1
1771 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1772 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 -
1773 [[ $VOL_COUNT ]] || return 1
1774 lvm_extra_lvs || return 1
1775 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1776 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating volume $VNAME from remaining space in $VGROUP\n" 0
1777 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1778 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1779 LVM='logical volume'; sleep 0.5
1780 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1781 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1787 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1791 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1792 if [[ -z $VOLUME_SIZE ]]; then
1794 break # allow bailing with escape or an empty choice
1795 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1796 ERR_SIZE=1 # size values can't begin with '0'
1798 # walk the string and make sure all but the last char are digits
1799 local lv=$((${#VOLUME_SIZE} - 1))
1800 for (( i=0; i<lv; i++ )); do
1801 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1803 if (( ERR_SIZE != 1 )); then
1804 case ${VOLUME_SIZE:$lv:1} in
1805 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1806 case ${VOLUME_SIZE:$lv:1} in
1807 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1808 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1815 if (( ERR_SIZE )); then
1816 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1829 until [[ $named ]]; do
1830 lvm_partitions || return 1
1831 lvm_group_name || return 1
1832 yesno "$_lvmnew" "\nCreate volume group: $VGROUP\n\nusing these partition(s): $LVM_PARTS\n" && named=true
1835 msg "$_lvmnew" "\nCreating volume group: $VGROUP\n" 0
1836 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1837 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1839 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1840 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1842 if [[ $SIZE_UNIT == 'G' ]]; then
1843 VGROUP_MB=$((SIZE * 1000))
1848 msg "$_lvmnew" "\nVolume group $VGROUP (${SIZE}$SIZE_UNIT) successfully created\n"
1854 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1855 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1856 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1858 if [[ $VGROUP || $v || $pv ]]; then
1859 if yesno "$_lvmdelall" "$_lvmdelask"; then
1860 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1861 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1862 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1866 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1876 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1877 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1880 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1882 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
1888 while (( VOL_COUNT > 1 )); do
1889 lvm_volume_name "$_lvmlvname" && lvm_lv_size || return 1
1890 msg "$_lvmnew (LV:$VOL_COUNT)" "\nCreating a $VOLUME_SIZE volume $VNAME in $VGROUP\n" 0
1891 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1892 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
1893 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
1901 part_find 'part|crypt' || return 1
1902 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
1903 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
1910 until [[ $VGROUP ]]; do
1911 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "lvgroup"
1912 if [[ -z $VGROUP ]]; then
1914 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || vgdisplay | grep -q "$VGROUP"; then
1915 msg "LVM Name Error" "$_lvmerrvgname"
1925 local txt="$1" default="mainvolume"
1926 (( VOL_COUNT > 1 )) && default="extvolume$VOL_COUNT"
1927 until [[ $VNAME ]]; do
1928 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
1929 if [[ -z $VNAME ]]; then
1931 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
1932 msg "LVM Name Error" "$_lvmerlvname"
1939 ###############################################################################
1945 no_bg_install || return 1
1946 dlg choice menu "LUKS Encryption" "$_luksmenu" \
1947 "$_luksnew" "cryptsetup -q luksFormat" \
1948 "$_luksopen" "cryptsetup open --type luks" \
1949 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
1950 "Back" "Return to the main menu"
1953 "$_luksnew") luks_basic || return 1 ;;
1954 "$_luksopen") luks_open || return 1 ;;
1955 "$_luksadv") luks_advanced || return 1 ;;
1963 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
1965 part_find 'part|crypt|lvm' || return 1
1967 if (( COUNT == 1 )); then
1968 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1970 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
1973 [[ $LUKS_PART ]] || return 1
1975 luks_pass "$_luksopen" || return 1
1976 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nUsing device/volume: $LUKS_PART\n" 0
1977 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
1978 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
1979 LUKS='encrypted'; luks_show
1987 typeset -a ans=(cryptroot) # default name to start
1989 until [[ $LUKS_PASS ]]; do
1991 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
1992 "Name:" 1 1 "${ans[0]}" 1 7 "$COLUMNS" 0 0 \
1993 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
1994 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
1996 mapfile -t ans <"$ANS"
1998 if [[ -z "${ans[0]}" ]]; then
1999 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2000 elif [[ -z "${ans[1]}" || "${ans[1]}" != "${ans[2]}" ]]; then
2001 LUKS_NAME="${ans[0]}"
2002 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2004 LUKS_NAME="${ans[0]}"
2005 LUKS_PASS="${ans[1]}"
2015 msg "$_luksnew" "\nEncrypted partition ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2020 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2022 part_find 'part|lvm' || return 1
2024 if [[ $AUTO_ROOT_PART ]]; then
2025 LUKS_PART="$AUTO_ROOT_PART"
2026 elif (( COUNT == 1 )); then
2027 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2029 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2032 [[ $LUKS_PART ]] || return 1
2033 luks_pass "$_luksnew"
2038 luks_setup || return 1
2039 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2040 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2041 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2042 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2043 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2044 LUKS='encrypted'; luks_show
2052 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2053 [[ $cipher ]] || return 1
2054 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2055 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2056 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2057 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2058 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2065 ###############################################################################
2067 # some help avoid repetition and improve usability of some commands
2068 # others are initial setup functions used before reaching the main loop
2072 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2077 # cleanup and exit the installer cleanly with exit code $1
2078 local e="$1" # when e is 127 unmount /run/archiso/bootmnt and reboot
2082 if [[ -d $MNT ]]; then
2084 if (( e == 127 )); then
2085 umount_dir /run/archiso/bootmnt && sleep 0.5 && reboot -f
2093 local var="$1" # assign output from dialog to var
2094 local dlg_t="$2" # dialog type (menu, check, input)
2095 local title="$3" # dialog title
2096 local body="$4" # dialog message
2097 local n=0 # number of items to display for menu and check dialogs
2099 shift 4 # shift off args assigned above
2101 # adjust n when passed a large list
2102 local l=$((LINES - 20))
2103 (( ($# / 2) > l )) && n=$l
2107 menu) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2108 check) dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1 ;;
2111 local def="$1" # assign default value for input
2113 if [[ $1 == 'limit' ]]; then
2114 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2116 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2120 # if answer file isn't empty read from it into $var
2121 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2126 # displays a message dialog
2127 # when more than 2 args the message will disappear after sleep time ($3)
2133 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$1" --title " $title " --infobox "$body\n" 0 0
2135 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2143 if (( $# == 0 )); then
2144 msg "No Session" "\nRunning live requires a session to use.\n\nExiting..\n" 2
2147 elif ! select_keymap; then
2150 elif ! net_connect; then
2151 msg "Not Connected" "\nRunning live requires an active internet connection.\n\nExiting..\n" 2
2155 pacman -Syyu archlinux-keyring --needed --noconfirm || die 1
2156 pacman -S $AL_BASE_PKGS xorg-xinit xorg-server --needed --noconfirm || die 1
2160 pacman -S git --needed --noconfirm || die 1
2161 mkdir -pv /root/suckless
2162 for i in dwm dmenu st; do
2163 git clone https://git.suckless.org/$i /root/suckless/$i && cd /root/suckless/$i && make PREFIX=/usr install
2166 i3-gaps|oepnbox|fluxbox|bspwm|awesome)
2167 pacman -S "$ses" $WM_BASE_PKGS ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2169 gnome|plasma|cinnamon|xfce4)
2170 pacman -S "$ses" ${WM_EXT[$ses]} xterm --needed --noconfirm || die 1
2172 *) echo "error: invalid session for -l, --live, see -h, --help"; die 1 ;;
2175 pacman -Scc --noconfirm
2176 rm -rf "/var/cache/pacman/pkg/"*
2177 cp -rfT /etc/skel /root || die 1
2178 sed -i "/exec/ c exec ${WM_SESSIONS[$ses]}" /root/.xinitrc
2179 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]}"
2187 usage: $1 [-hdl] [session]
2190 -h, --help print this message and exit
2191 -l, --live install and setup a live session
2192 -d, --debug enable debugging and log output to $DBG
2195 i3-gaps - A fork of i3wm with more features including gaps
2196 openbox - A lightweight, powerful, and highly configurable stacking wm
2197 dwm - A dynamic WM for X that manages windows in tiled, floating, or monocle layouts
2198 awesome - A customized Awesome WM session created by @elanapan
2199 bspwm - A tiling wm that represents windows as the leaves of a binary tree
2200 fluxbox - A lightweight and highly-configurable window manager
2201 gnome - A desktop environment that aims to be simple and easy to use
2202 cinnamon - A desktop environment combining traditional desktop with modern effects
2203 plasma - A kde software project currently comprising a full desktop environment
2204 xfce4 - A lightweight and modular desktop environment based on gtk+2/3
2212 local title="$1" body="$2" yes='Yes' no='No'
2213 (( $# >= 3 )) && yes="$3"
2214 (( $# >= 4 )) && no="$4"
2216 if (( $# == 5 )); then
2217 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2219 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2225 arch-chroot "$MNT" bash -c "$1"
2230 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2240 "\e]P0191919" # #191919
2241 "\e]P1D15355" # #D15355
2242 "\e]P2609960" # #609960
2243 "\e]P3FFCC66" # #FFCC66
2244 "\e]P4255A9B" # #255A9B
2245 "\e]P5AF86C8" # #AF86C8
2246 "\e]P62EC8D3" # #2EC8D3
2247 "\e]P7949494" # #949494
2248 "\e]P8191919" # #191919
2249 "\e]P9D15355" # #D15355
2250 "\e]PA609960" # #609960
2251 "\e]PBFF9157" # #FF9157
2252 "\e]PC4E88CF" # #4E88CF
2253 "\e]PDAF86C8" # #AF86C8
2254 "\e]PE2ec8d3" # #2ec8d3
2255 "\e]PFE1E1E1" # #E1E1E1
2258 [[ $TERM == 'linux' ]] && printf "%b" "${colors[@]}" && clear
2263 [ $? -eq 0 ] && return 0
2265 local fatal=0 err=""
2266 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2267 [[ -z $err ]] && err="no error message was found"
2269 (( $1 == 1 )) && { fatal=1; shift; }
2271 local txt="\nCommand: $1\n\n\n\nError: $err\n\n"
2273 if (( fatal )); then
2274 msg "Install Error" "${txt}Errors at this stage are fatal, the install cannot continue.\n"
2275 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2279 msg "Install Error" "${txt}Errors at this stage are non-fatal and may be fixed or ignored depending on the error.\n"
2287 if (( $1 >= 0 )) && ! grep -qw "$MNT" /proc/mounts; then
2288 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2290 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2291 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2293 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2294 msg "No User" "\nA user must be created first.\n" 2
2296 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2297 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2300 (( i )) # return code
2305 mount | grep -q 'swap' && swapoff -a
2307 if [[ -d $dir ]] && mount | grep -q "on $dir "; then
2308 if ! umount "$dir" 2>/dev/null; then
2310 umount -f "$dir" 2>/dev/null || umount -l "$dir"
2318 msg "Network Connect" "\nVerifying network connection\n" 0
2319 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2324 if chk_connect; then
2326 elif hash nmtui >/dev/null 2>&1; then
2328 if [[ $TERM == 'linux' ]]; then
2329 printf "%b" "\e]P1191919" "\e]P4191919"
2331 printf "%b" "\e]P1D15355" "\e]P4255a9b"
2336 elif hash wifi-menu >dev/null 2>&1; then
2346 [[ $BG_PID ]] || return 0
2347 msg "Install Running" "\nA background install process is currently running.\n" 2
2353 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2355 if [[ $IGNORE_DEV ]]; then
2356 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2358 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2361 if [[ -z $SYS_DEVS ]]; then
2362 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2367 while read -r line; do
2369 done <<< "$SYS_DEVS"
2376 # amd-ucode is not needed it's provided by linux-firmware
2377 # elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2379 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2383 modprobe -q efivarfs >/dev/null 2>&1
2385 _prep="\nOnce a step is finished a step you will be returned here, if the step was successful the cursor will be advanced to the next step.\nIf a step is unsuccessful the cursor will be placed on the step required to advance (when possible).\n\nTo begin the install you should have:\n\n - A root (/) partition mounted."
2386 if [[ -d /sys/firmware/efi/efivars ]]; then
2388 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2389 _prep+="\n - An EFI boot partition mounted."
2393 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2394 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2395 _prep+="\n - Basic system configuration, kernel, shell, login, packages, etc..\n\nOnce you're happy with the choices and the required steps are complete, the main install can be started."
2398 ###############################################################################
2401 # enable some nicer colours in the linux console
2404 if (( UID != 0 )); then
2405 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2407 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2408 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2412 -d|--debug) debug ;;
2413 -h|--help) usage "$0" ;;
2414 -l|--live) shift; live "$@" ;;
2418 # trap ^C to perform cleanup
2419 trap 'printf "\n^C\n" && die 1' INT
2424 msg "Welcome to the $DIST Installer" "$_welcome"
2426 if ! select_keymap; then
2428 elif ! net_connect; then
2429 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2438 # vim:fdm=marker:fmr={,}