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
8 VER="2.0.40" # installer version
9 DIST="ArchLabs" # linux distributor
10 MNT="/mnt" # install mountpoint
11 ANS="/tmp/ans" # dialog answer file
14 # --------------------------------------------- #
15 # if you manually mount your partitions then you
16 # need to set these values to avoid issues.
17 # --------------------------------------------- #
19 # root partition, eg/ /dev/sda2
22 # boot partition, required on UEFI eg. /dev/sda1
25 # device used for some bootloader install process, eg. /dev/sda
28 # bootloader to use, can be:
29 # UEFI: grub, syslinux, efistub, systemd-boot, refind-efi
30 # BIOS: grub, syslinux
33 # directory to mount the boot partition (if any) for most bootloaders
34 # this will need to be 'boot' however a popular one for grub is 'boot/efi'
37 # swap partition or file path
40 # swap size, only used when creating a swapfile
43 # --------------------------------------------- #
45 # bulk default values {
47 EXMNT='' # holder for additional partitions while mounting
48 EXMNTS='' # when an extra partition is mounted append it's info
50 FONT="ter-i16n" # font used for the linux console
51 HOOKS="shutdown" # list of additional HOOKS to add in /etc/mkinitcpio.conf
53 LOGINRC='' # login shell rc file, eg. .zprofile, .bash_profile, .profile
54 LOGIN_WM='' # default login session to be placed in ~/.xinitrc
55 INSTALL_WMS='' # space separated list of chosen wm/de
57 UCODE='' # cpu microcode (if any), eg. amd-ucode, intel-ucode
58 KERNEL='' # can be linux, linux-lts, linux-zen, or linux-hardened
59 MYSHELL='' # full path for the shell, eg. /usr/bin/zsh
61 WM_PKGS='' # full list of packages added during wm/de choice
62 PACKAGES='' # list of all packages to install including WM_PKGS
63 USER_PKGS='' # packages selected by the user during install
65 NEWUSER='' # username for the new user
66 USER_PASS='' # new user's password
67 ROOT_PASS='' # root password
69 LUKS='' # empty when not using encryption
70 LUKS_DEV='' # boot parameter string for LUKS
71 LUKS_PART='' # partition used for encryption
72 LUKS_PASS='' # encryption password
73 LUKS_UUID='' # encrypted partition UUID
74 LUKS_NAME='' # name used for encryption
76 LVM='' # empty when not using lvm
77 LVM_PARTS='' # partitions used for volume group
78 VGROUP_MB=0 # available space in volume group
80 WARN='' # issued mounting/partitioning warning
81 SEP_BOOT='' # separate boot partition for BIOS
82 AUTOLOGIN='' # enable autologin for xinit
83 CONFIG_DONE='' # basic configuration is finished
84 BROADCOM_WL='' # fixes for broadcom cards eg. BCM4352
86 FORMATTED='' # partitions we formatted and should allow skipping
87 AUTO_ROOT_PART='' # root value from auto partition
88 AUTO_BOOT_PART='' # boot value from auto partition
90 # iso base, pacstrap when running the installer from a stock arch iso
91 ISO_BASE="arch-install-scripts b43-firmware b43-fwcutter broadcom-wl clonezilla dhclient dhcpcd ethtool "
92 ISO_BASE+="exfat-utils f2fs-tools gptfdisk vim hdparm ipw2100-fw ipw2200-fw nfs-utils nilfs-utils ntfs-3g "
93 ISO_BASE+="pacman-contrib parted rsync sdparm smartmontools wget wireless_tools wpa_actiond xl2tpd dialog parted "
94 ISO_BASE+="alsa-firmware alsa-lib alsa-plugins pulseaudio pulseaudio-alsa networkmanager w3m htop wireless-regdb "
95 ISO_BASE+="wpa_supplicant lm_sensors lsb-release p7zip pamixer reflector unrar ranger terminus-font ttf-dejavu archlabs-keyring"
97 # archlabs base packages
98 AL_BASE_PKGS="archlabs-skel-base archlabs-fonts archlabs-themes archlabs-dARK archlabs-icons archlabs-wallpapers archlabs-scripts"
100 # baseline (usually installed in the background)
101 BASE_PKGS="base-devel xorg xorg-drivers xorg-xinit sudo git gvfs gtk3 gtk-engines gtk-engine-murrine pavucontrol tumbler "
102 BASE_PKGS+="playerctl ffmpeg gstreamer libmad libmatroska gst-libav gst-plugins-base gst-plugins-good scrot"
104 # extras for window managers
105 WM_BASE_PKGS="arandr archlabs-networkmanager-dmenu xdg-user-dirs nitrogen polkit-gnome volumeicon xclip exo "
106 WM_BASE_PKGS+="xdotool compton wmctrl gnome-keyring dunst feh gsimplecal xfce4-power-manager xfce4-settings laptop-detect"
109 SEL=0 # currently selected menu item
110 ERR="/tmp/errlog" # error log used internally
111 DBG="/tmp/debuglog" # debug log when passed -d
112 RUN="/run/archiso/bootmnt/arch/boot" # path for live /boot
113 VM="$(dmesg | grep -i "hypervisor")" # is the system a vm
116 export DIALOGOPTS="--cr-wrap"
120 # giant ugly variable container :P {
122 # RAM in the system in MB
123 SYS_MEM="$(awk '/MemTotal/ {
124 print int($2 / 1024)"M"
127 # locales from /etc/locale.gen
128 LOCALES="$(awk '/\.UTF-8/ {
135 # linux console keyboard mappings
136 CMAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{
137 gsub(/\.map\.gz|.*\//, "")
141 # terminal size definitions
143 [[ $LINES ]] || LINES=$(tput lines)
144 [[ $COLUMNS ]] || COLUMNS=$(tput cols)
145 SHL=$((LINES - 20)) # }
150 # commands used to install each bootloader (most get modified during runtime) {
152 [refind-efi]='refind-install'
153 [grub]='grub-install --recheck --force'
154 [syslinux]='syslinux-install_update -i -a -m'
155 [efistub]='efibootmgr -v -d /dev/sda -p 1 -c -l'
156 [systemd-boot]='bootctl --path=/boot install'
159 # executable name for each wm/de {
160 declare -A WM_SESSIONS=(
166 [gnome]='gnome-session'
167 [fluxbox]='startfluxbox'
168 [openbox]='openbox-session'
169 [cinnamon]='cinnamon-session'
172 # packages installed for each wm/de {
176 [plasma]='kdebase-meta'
177 [bspwm]='sxhkd archlabs-skel-bspwm rofi archlabs-polybar'
178 [fluxbox]='archlabs-skel-fluxbox archlabs-polybar jgmenu rofi lxmenu-data'
179 [i3-gaps]='i3status perl-anyevent-i3 archlabs-skel-i3-gaps rofi archlabs-polybar'
180 [openbox]='obconf archlabs-skel-openbox jgmenu archlabs-polybar tint2 conky rofi lxmenu-data'
181 [xfce4]='xfce4-goodies xfce4-pulseaudio-plugin network-manager-applet volumeicon rofi archlabs-skel-xfce4'
184 # files that can be edited after install is complete {
185 declare -A EDIT_FILES=(
188 [sudoers]='/etc/sudoers'
189 [crypttab]='/etc/crypttab'
190 [pacman]='/etc/pacman.conf'
191 [console]='/etc/vconsole.conf'
192 [mkinitcpio]='/etc/mkinitcpio.conf'
193 [hostname]='/etc/hostname /etc/hosts'
194 [bootloader]="/boot/loader/entries/$DIST.conf"
195 [locale]='/etc/locale.conf /etc/default/locale'
196 [keyboard]='/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard'
199 # mkfs command for formatting each offered filesystem {
204 [ntfs]='mkfs.ntfs -q'
205 [ext2]='mkfs.ext2 -q'
206 [ext3]='mkfs.ext3 -q'
207 [ext4]='mkfs.ext4 -q'
208 [vfat]='mkfs.vfat -F32'
209 [nilfs2]='mkfs.nilfs2 -q'
210 [reiserfs]='mkfs.reiserfs -q'
213 # mount options for each offered filesystem (if any {
219 [jfs]='discard errors=continue errors=panic nointegrity'
220 [reiserfs]='acl nolog notail replayonly user_xattr off'
221 [ext4]='discard dealloc nofail noacl relatime noatime nobarrier nodelalloc'
222 [xfs]='discard filestreams ikeep largeio noalign nobarrier norecovery noquota wsync'
223 [nilfs2]='discard nobarrier errors=continue errors=panic order=relaxed order=strict norecovery'
224 [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'
227 # PKG_EXT: if you add a package to $PACKAGES in any dialog {
228 # and it uses/requires some additional packages,
229 # you can add them here to keep it simple: [package]="extra"
230 # duplicates are removed with `uniq` before install
234 [mupdf]='mupdf-tools'
235 [qt5ct]='qt5-styleplugins'
236 [vlc]='qt5ct qt5-styleplugins'
237 [zathura]='zathura-pdf-poppler'
238 [noto-fonts]='noto-fonts-emoji'
239 [cairo-dock]='cairo-dock-plug-ins'
240 [qutebrowser]='qt5ct qt5-styleplugins'
241 [qbittorrent]='qt5ct qt5-styleplugins'
242 [transmission-qt]='qt5ct qt5-styleplugins'
243 [kdenlive]='kdebase-meta dvdauthor frei0r-plugins breeze breeze-gtk qt5ct qt5-styleplugins'
251 # Basics (somewhat in order)
252 _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"
253 _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"
254 _device="\nSelect a device to use from the list below.\n\nDevices (/dev) are the available drives on the system. /sda, /sdb, /sdc ..."
255 _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."
256 _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."
257 _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"
258 _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 (and BIOS using LUKS without LVM) require a separate boot partition (100-512M)."
259 _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."
260 _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."
261 _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."
262 _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"
263 _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."
264 _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."
265 _exmnt="\nWhere do you want the partition mounted?\n\nEnsure the name begins with a slash (/).\nExamples include: /usr, /home, /var, etc."
266 _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 the [Up] and [Down] arrows to switch between input fields, [Tab] to toggle between input fields and the buttons, and [Enter] to accept."
267 _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."
268 _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"
269 _timez="\nThe time zone is used to set the system clock.\n\nSelect your country or continent from the list below"
270 _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."
271 _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."
272 _login="\nSelect which of your session choices to use for the initial login.\n\nYou can be change this later by editing your ~/.xinitrc"
273 _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."
274 _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] or Ctrl-z again to resume the installer, if you want to avoid the automatic reboot using Ctrl-c will cleanly exit."
277 _luksnew="Basic LUKS Encryption"
278 _luksadv="Advanced LUKS Encryption"
279 _luksopen="Open Existing LUKS Partition"
280 _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."
281 _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."
282 _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)."
285 _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."
286 _lvmnew="Create Volume Group and Volume(s)"
287 _lvmdel="Delete an Existing Volume Group"
288 _lvmdelall="Delete ALL Volume Group(s) and Volume(s)"
289 _lvmvgname="\nEnter a name for the volume group (VG) being created from the partition(s) selected."
290 _lvmlvname="\nEnter a name for the logical volume (LV) being created.\n\nThis is similar to setting a label for a partition."
291 _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."
292 _lvmdelask="\nConfirm deletion of volume group(s) and logical volume(s).\n\nDeleting a volume group, will delete all logical volumes within it.\n"
295 _errexpart="\nCannot mount partition due to a problem with the mountpoint.\n\nEnsure it begins with a slash (/) followed by atleast one character.\n"
296 _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"
297 _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"
298 _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"
299 _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"
300 _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"
301 _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"
307 ###############################################################################
312 (( SEL < 12 )) && (( SEL++ ))
314 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Prepare " --default-item $SEL --cancel-label 'Exit' --menu "$_prep" 0 0 0 \
315 1 "Device tree (optional)" \
316 2 "Partitioning (optional)" \
317 3 "LUKS setup (optional)" \
318 4 "LVM setup (optional)" \
319 5 "Mount partitions" \
320 6 "System bootloader" \
321 7 "User and password" \
322 8 "System configuration" \
323 9 "Select WM/DE (optional)" \
324 10 "Select Packages (optional)" \
325 11 "View configuration (optional)" \
326 12 "Start the installation" 2>"$ANS"
329 [[ -z $WARN && $SEL =~ (2|5) ]] && { msg "Data Warning" "$_warn"; WARN=true; }
332 2) part_menu || (( SEL-- )) ;;
333 3) luks_menu || (( SEL-- )) ;;
334 4) lvm_menu || (( SEL-- )) ;;
335 5) select_menu || (( SEL-- )) ;;
336 6) prechecks 0 && { select_boot || (( SEL-- )); } ;;
337 7) prechecks 1 && { select_mkuser || (( SEL-- )); } ;;
338 8) prechecks 2 && { select_config || (( SEL-- )); } ;;
339 9) prechecks 3 && { select_sessions || (( SEL-- )); } ;;
340 10) prechecks 3 && { select_packages || (( SEL-- )); } ;;
341 11) prechecks 3 && select_show ;;
342 12) prechecks 3 && install_main ;;
343 *) yesno "Exit" "\nUnmount partitions (if any) and exit the installer?\n" && die 0
349 if [[ $SYS == 'BIOS' ]]; then
350 dlg BOOTLDR menu "BIOS Bootloader" "\nSelect which bootloader to use." \
351 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
352 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network" || return 1
354 dlg BOOTLDR menu "UEFI Bootloader" "\nSelect which bootloader to use." \
355 "systemd-boot" "A simple UEFI boot manager which executes configured EFI images" \
356 "grub" "The Grand Unified Bootloader, standard among many Linux distributions" \
357 "refind-efi" "A UEFI boot manager that aims to be platform neutral and simplify multi-boot" \
358 "efistub" "Boot the kernel image directly (no chainloading support)" \
359 "syslinux" "A collection of boot loaders for booting drives, CDs, or over the network (no chainloading support)" || return 1
367 local cmd="${BCMDS[$BOOTLDR]}"
368 local pkgs="${USER_PKGS// / } ${PACKAGES// / }"
369 [[ $BOOT_PART ]] && mnt="/$BOOTDIR"
370 [[ $INSTALL_WMS == *dwm* ]] && pkgs="dwm st dmenu $pkgs"
371 msg "Show Configuration" "
373 ---------- PARTITION CONFIGURATION ------------
375 Root: ${ROOT_PART:-none}
376 Boot: ${BOOT_PART:-${BOOT_DEV:-none}}
378 Swap: ${SWAP_PART:-none}
379 Size: ${SWAP_SIZE:-none}
384 Extra: ${EXMNTS:-${EXMNT:-none}}
385 Hooks: ${HOOKS:-none}
388 ---------- BOOTLOADER CONFIGURATION -----------
390 Bootloader: ${BOOTLDR:-none}
391 Mountpoint: ${mnt:-none}
392 Command: ${cmd:-none}
395 ------------ SYSTEM CONFIGURATION -------------
397 Locale: ${MYLOCALE:-none}
398 Keymap: ${KEYMAP:-none}
399 Hostname: ${MYHOST:-none}
400 Timezone: ${ZONE:-none}/${SUBZ:-none}
403 ------------ USER CONFIGURATION --------------
405 User: ${NEWUSER:-none}
406 Shell: ${MYSHELL:-none}
407 Session: ${LOGIN_WM:-none}
408 Autologin: ${AUTOLOGIN:-none}
409 Login Method: ${LOGIN_TYPE:-none}
412 ------------ PACKAGES AND MIRRORS -------------
414 Kernel: ${KERNEL:-none}
415 Sessions: ${INSTALL_WMS:-none}
416 Packages: $(print4 "${pkgs:-none}")
422 if (( WM_NUM == 1 )); then
423 LOGIN_WM="${WM_SESSIONS[$INSTALL_WMS]}"
425 dlg LOGIN_WM menu "Login Session" "$_login" $LOGIN_CHOICES || return 1
426 LOGIN_WM="${WM_SESSIONS[$LOGIN_WM]}"
429 local txt="\nDo you want autologin enabled for $NEWUSER?\n\nThe following two files will be created (disable autologin by remove them):\n\n - /home/$NEWUSER/$LOGINRC (this runs startx when logging in on tty1)\n - /etc/systemd/system/getty@tty1.service.d/autologin.conf (this logs in $NEWUSER without a password)\n"
430 yesno "Autologin" "$txt" && AUTOLOGIN=true || AUTOLOGIN=''
431 EDIT_FILES[login]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
439 until [[ $CONFIG_DONE ]]; do
442 dlg MYSHELL menu "Shell" "\nChoose which shell to use." \
443 /usr/bin/zsh 'A very advanced and programmable command interpreter (shell) for UNIX' \
444 /bin/bash 'The GNU Bourne Again shell, standard in many GNU/Linux distributions' \
445 /usr/bin/mksh 'The MirBSD Korn Shell - an enhanced version of the public domain ksh' || return 1
448 1) dlg MYHOST input "Hostname" "$_hostname" "${DIST,,}" limit || { i=0; continue; } ;;
449 2) dlg MYLOCALE menu "Locale" "$_locale" $LOCALES || { i=1; continue; } ;;
451 until [[ $ZONE && $SUBZ ]]; do
452 dlg ZONE menu "Timezone" "$_timez" America - Australia - Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica - || break
453 dlg SUBZ menu "Timezone" "$_timesubz" $(awk '/'"$ZONE"'\// {gsub(/'"$ZONE"'\//, ""); print $3 " - "}' /usr/share/zoneinfo/zone.tab | sort) || continue
454 yesno "Timezone" "\nConfirm time zone: $ZONE/$SUBZ\n" || unset ZONE
456 [[ $ZONE && $SUBZ ]] || { i=2; continue; } ;;
458 dlg KERNEL menu "Kernel" "\nChoose which kernel to use." \
459 linux 'Vanilla linux kernel and modules, with a few patches applied' \
460 linux-lts 'Long-term support (LTS) linux kernel and modules' \
461 linux-zen 'A effort of kernel hackers to provide the best kernel for everyday systems' \
462 linux-hardened 'A security-focused linux kernel with hardening patches to mitigate exploits' || { i=3; continue; }
467 (( i++ )) # progress through to the next choice
471 '/bin/bash') LOGINRC='.bash_profile' ;;
472 '/usr/bin/zsh') LOGINRC='.zprofile' ;;
473 '/usr/bin/mksh') LOGINRC='.profile' ;;
482 local v='' u='' p='' p2='' rp='' rp2=''
484 until [[ $NEWUSER ]]; do
487 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " User " --mixedform "$_user" 0 0 0 \
488 "Username:" 1 1 "$u" 1 11 "$COLUMNS" 0 0 \
489 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
490 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 \
491 "--- Root password, if left empty the user password will be used ---" 6 1 '' 6 68 "$COLUMNS" 0 2 \
492 "Password:" 8 1 '' 8 11 "$COLUMNS" 0 1 \
493 "Password2:" 9 1 '' 9 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
495 while read -r line; do
506 # root passwords empty, so use the user passwords
507 [[ -z $rp && -z $rp2 ]] && { rp="$p"; rp2="$p2"; }
509 # make sure a username was entered and that the passwords match
510 if [[ ${#u} -eq 0 || $u =~ \ |\' || $u =~ [^a-z0-9] ]]; then
511 msg "Invalid Username" "\nIncorrect user name.\n\nPlease try again.\n"; u=''
512 elif [[ -z $p ]]; then
513 msg "Empty Password" "\nThe user password cannot be left empty.\n\nPlease try again.\n"
514 elif [[ "$p" != "$p2" ]]; then
515 msg "Password Mismatch" "\nThe user passwords do not match.\n\nPlease try again.\n"
516 elif [[ "$rp" != "$rp2" ]]; then
517 msg "Password Mismatch" "\nThe root passwords do not match.\n\nPlease try again.\n"
529 dlg KEYMAP menu "Keyboard Layout" "$_keymap" \
530 us English cm English gb English au English gh English \
531 za English ng English ca French 'cd' French gn French \
532 tg French fr French de German at German ch German \
533 es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic \
534 sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian \
535 sk Slovak nl Dutch it Italian hu Hungarian cn Chinese \
536 tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai \
537 la Lao pl Polish se Swedish is Icelandic 'fi' Finnish \
538 dk Danish be Belgian in Indian al Albanian am Armenian \
539 bd Bangla ba Bosnian 'bg' Bulgarian dz Berber mm Burmese \
540 hr Croatian gr Greek il Hebrew ir Persian iq Iraqi \
541 af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz \
542 kz Kazakh lt Lithuanian mt Maltese mn Mongolian ro Romanian \
543 no Norwegian rs Serbian si Slovenian tj Tajik lk Sinhala \
544 tr Turkish uz Uzbek ie Irish pk Urdu 'mv' Dhivehi \
545 np Nepali et Amharic sn Wolof ml Bambara tz Swahili \
546 ke Swahili bw Tswana ph Filipino my Malay tm Turkmen \
547 id Indonesian bt Dzongkha lv Latvian md Moldavian mao Maori \
548 by Belarusian az Azerbaijani mk Macedonian kh Khmer epo Esperanto \
549 me Montenegrin || return 1
551 if [[ $CMAPS == *"$KEYMAP"* ]]; then
554 dlg CMAP menu "Console Keymap" "$_vconsole" $CMAPS || return 1
557 if [[ $DISPLAY && $TERM != 'linux' ]]; then
558 setxkbmap "$KEYMAP" >/dev/null 2>&1
560 loadkeys "$CMAP" >/dev/null 2>&1
570 dlg INSTALL_WMS check "Sessions" "$_sessions\n" \
571 i3-gaps "A fork of i3wm with more features including gaps" "$(ofn i3-gaps "${INSTALL_WMS[*]}")" \
572 openbox "A lightweight, powerful, and highly configurable stacking wm" "$(ofn openbox "${INSTALL_WMS[*]}")" \
573 bspwm "A tiling wm that represents windows as the leaves of a binary tree" "$(ofn bspwm "${INSTALL_WMS[*]}")" \
574 dwm "A fork of dwm, with more layouts and features" "$(ofn dwm "${INSTALL_WMS[*]}")" \
575 fluxbox "A lightweight and highly-configurable window manager" "$(ofn fluxbox "${INSTALL_WMS[*]}")" \
576 gnome "A desktop environment that aims to be simple and easy to use" "$(ofn gnome "${INSTALL_WMS[*]}")" \
577 cinnamon "A desktop environment combining traditional desktop with modern effects" "$(ofn cinnamon "${INSTALL_WMS[*]}")" \
578 plasma "A kde software project currently comprising a full desktop environment" "$(ofn plasma "${INSTALL_WMS[*]}")" \
579 xfce4 "A lightweight and modular desktop environment based on gtk+2/3" "$(ofn xfce4 "${INSTALL_WMS[*]}")" || return 1
582 while IFS=' ' read -r i; do
584 done <<< "$INSTALL_WMS"
587 WM_PKGS="${INSTALL_WMS/dwm/}" # remove dwm from package list
588 WM_PKGS="${WM_PKGS// / }" # remove double spaces
589 WM_PKGS="${WM_PKGS# }" # remove leading space
591 # add archlabs base when choosing any session
592 [[ $WM_PKGS ]] && WM_PKGS+=" $AL_BASE_PKGS"
594 for i in $INSTALL_WMS; do
595 LOGIN_CHOICES+="$i - "
596 [[ ${WM_EXT[$i]} && $WM_PKGS != *"${WM_EXT[$i]}"* ]] && WM_PKGS+=" ${WM_EXT[$i]}"
599 select_login || return 1
601 while IFS=' ' read -r pkg; do
602 [[ $PACKAGES != *"$pkg"* ]] && PACKAGES+=" $pkg"
610 dlg USER_PKGS check " Packages " "$_packages" \
611 abiword "A Fully-featured word processor" "$(ofn abiword "${USER_PKGS[*]}")" \
612 alacritty "A cross-platform, GPU-accelerated terminal emulator" "$(ofn alacritty "${USER_PKGS[*]}")" \
613 atom "An open-source text editor developed by GitHub" "$(ofn atom "${USER_PKGS[*]}")" \
614 audacious "A free and advanced audio player based on GTK+" "$(ofn audacious "${USER_PKGS[*]}")" \
615 audacity "A program that lets you manipulate digital audio waveforms" "$(ofn audacity "${USER_PKGS[*]}")" \
616 cairo-dock "Light eye-candy fully themable animated dock" "$(ofn cairo-dock "${USER_PKGS[*]}")" \
617 calligra "A set of applications for productivity" "$(ofn calligra "${USER_PKGS[*]}")" \
618 chromium "An open-source web browser based on the Blink rendering engine" "$(ofn chromium "${USER_PKGS[*]}")" \
619 clementine "A modern music player and library organizer" "$(ofn clementine "${USER_PKGS[*]}")" \
620 cmus "A small, fast and powerful console music player" "$(ofn cmus "${USER_PKGS[*]}")" \
621 deadbeef "A GTK+ audio player for GNU/Linux" "$(ofn deadbeef "${USER_PKGS[*]}")" \
622 deluge "A BitTorrent client written in python" "$(ofn deluge "${USER_PKGS[*]}")" \
623 docky "Full fledged dock for opening applications and managing windows" "$(ofn docky "${USER_PKGS[*]}")" \
624 emacs "An extensible, customizable, self-documenting real-time display editor" "$(ofn emacs "${USER_PKGS[*]}")" \
625 epiphany "A GNOME web browser based on the WebKit rendering engine" "$(ofn epiphany "${USER_PKGS[*]}")" \
626 evince "A document viewer" "$(ofn evince "${USER_PKGS[*]}")" \
627 evolution "Manage your email, contacts and schedule" "$(ofn evolution "${USER_PKGS[*]}")" \
628 file-roller "Create and modify archives" "$(ofn file-roller "${USER_PKGS[*]}")" \
629 firefox "A popular open-source web browser from Mozilla" "$(ofn firefox "${USER_PKGS[*]}")" \
630 gcolor2 "A simple GTK+2 color selector" "$(ofn gcolor2 "${USER_PKGS[*]}")" \
631 geany "A fast and lightweight IDE" "$(ofn geany "${USER_PKGS[*]}")" \
632 geary "A lightweight email client for the GNOME desktop" "$(ofn geary "${USER_PKGS[*]}")" \
633 gimp "GNU Image Manipulation Program" "$(ofn gimp "${USER_PKGS[*]}")" \
634 gnome-disk-utility "Disk Management Utility" "$(ofn gnome-disk-utility "${USER_PKGS[*]}")" \
635 gnome-system-monitor "View current processes and monitor system state" "$(ofn gnome-system-monitor "${USER_PKGS[*]}")" \
636 gparted "A GUI frontend for creating and manipulating partition tables" "$(ofn gparted "${USER_PKGS[*]}")" \
637 gpick "Advanced color picker using GTK+ toolkit" "$(ofn gpick "${USER_PKGS[*]}")" \
638 gpicview "Lightweight image viewer" "$(ofn gpicview "${USER_PKGS[*]}")" \
639 guvcview "Capture video from camera devices" "$(ofn guvcview "${USER_PKGS[*]}")" \
640 hexchat "A popular and easy to use graphical IRC client" "$(ofn hexchat "${USER_PKGS[*]}")" \
641 inkscape "Professional vector graphics editor" "$(ofn inkscape "${USER_PKGS[*]}")" \
642 irssi "Modular text mode IRC client" "$(ofn irssi "${USER_PKGS[*]}")" \
643 kdenlive "A popular non-linear video editor for Linux" "$(ofn kdenlive "${USER_PKGS[*]}")" \
644 krita "Edit and paint images" "$(ofn krita "${USER_PKGS[*]}")" \
645 libreoffice-fresh "Full featured office suite" "$(ofn libreoffice-fresh "${USER_PKGS[*]}")" \
646 lollypop "A new music playing application" "$(ofn lollypop "${USER_PKGS[*]}")" \
647 mousepad "A simple text editor" "$(ofn mousepad "${USER_PKGS[*]}")" \
648 mpd "A flexible, powerful, server-side application for playing music" "$(ofn mpd "${USER_PKGS[*]}")" \
649 mpv "A media player based on mplayer" "$(ofn mpv "${USER_PKGS[*]}")" \
650 mupdf "Lightweight PDF and XPS viewer" "$(ofn mupdf "${USER_PKGS[*]}")" \
651 mutt "Small but very powerful text-based mail client" "$(ofn mutt "${USER_PKGS[*]}")" \
652 nautilus "The default file manager for Gnome" "$(ofn nautilus "${USER_PKGS[*]}")" \
653 ncmpcpp "A mpd client and almost exact clone of ncmpc with some new features" "$(ofn ncmpcpp "${USER_PKGS[*]}")" \
654 neovim "A fork of Vim aiming to improve user experience, plugins, and GUIs." "$(ofn neovim "${USER_PKGS[*]}")" \
655 nicotine+ "A graphical client for Soulseek" "$(ofn nicotine+ "${USER_PKGS[*]}")" \
656 noto-fonts "Google Noto fonts" "$(ofn noto-fonts "${USER_PKGS[*]}")" \
657 noto-fonts-cjk "Google Noto CJK fonts (Chinese, Japanese, Korean)" "$(ofn noto-fonts-cjk "${USER_PKGS[*]}")" \
658 obs-studio "Free opensource streaming/recording software" "$(ofn obs-studio "${USER_PKGS[*]}")" \
659 openshot "An open-source, non-linear video editor for Linux" "$(ofn openshot "${USER_PKGS[*]}")" \
660 opera "A Fast and secure, free of charge web browser from Opera Software" "$(ofn opera "${USER_PKGS[*]}")" \
661 pcmanfm "A fast and lightweight file manager based in Lxde" "$(ofn pcmanfm "${USER_PKGS[*]}")" \
662 pidgin "Multi-protocol instant messaging client" "$(ofn pidgin "${USER_PKGS[*]}")" \
663 plank "An elegant, simple, and clean dock" "$(ofn plank "${USER_PKGS[*]}")" \
664 qbittorrent "An advanced BitTorrent client" "$(ofn qbittorrent "${USER_PKGS[*]}")" \
665 qpdfview "A tabbed PDF viewer" "$(ofn qpdfview "${USER_PKGS[*]}")" \
666 qt5ct "GUI for managing Qt based application themes, icons, and fonts" "$(ofn qt5ct "${USER_PKGS[*]}")" \
667 qutebrowser "A keyboard-focused vim-like web browser based on Python and PyQt5" "$(ofn qutebrowser "${USER_PKGS[*]}")" \
668 rhythmbox "A Music playback and management application" "$(ofn rhythmbox "${USER_PKGS[*]}")" \
669 rxvt-unicode "A unicode enabled rxvt-clone terminal emulator" "$(ofn rxvt-unicode "${USER_PKGS[*]}")" \
670 sakura "A terminal emulator based on GTK and VTE" "$(ofn sakura "${USER_PKGS[*]}")" \
671 simplescreenrecorder "A feature-rich screen recorder" "$(ofn simplescreenrecorder "${USER_PKGS[*]}")" \
672 steam "A popular game distribution platform by Valve" "$(ofn steam "${USER_PKGS[*]}")" \
673 surf "A simple web browser based on WebKit2/GTK+" "$(ofn surf "${USER_PKGS[*]}")" \
674 terminator "Terminal emulator that supports tabs and grids" "$(ofn terminator "${USER_PKGS[*]}")" \
675 termite "A minimal VTE-based terminal emulator" "$(ofn termite "${USER_PKGS[*]}")" \
676 thunar "A modern file manager for the Xfce Desktop Environment" "$(ofn thunar "${USER_PKGS[*]}")" \
677 thunderbird "Standalone mail and news reader from mozilla" "$(ofn thunderbird "${USER_PKGS[*]}")" \
678 tilda "A GTK based drop down terminal for Linux and Unix" "$(ofn tilda "${USER_PKGS[*]}")" \
679 tilix "A tiling terminal emulator for Linux using GTK+ 3" "$(ofn tilix "${USER_PKGS[*]}")" \
680 transmission-cli "Free BitTorrent client CLI" "$(ofn transmission-cli "${USER_PKGS[*]}")" \
681 transmission-gtk "Free BitTorrent client GTK+ GUI" "$(ofn transmission-gtk "${USER_PKGS[*]}")" \
682 transmission-qt "Free BitTorrent client Qt GUI" "$(ofn transmission-qt "${USER_PKGS[*]}")" \
683 ttf-anonymous-pro "A family fixed-width fonts designed with code in mind" "$(ofn ttf-anonymous-pro "${USER_PKGS[*]}")" \
684 ttf-fira-code "Monospaced font with programming ligatures" "$(ofn ttf-fira-code "${USER_PKGS[*]}")" \
685 ttf-font-awesome "Iconic font designed for Bootstrap" "$(ofn ttf-font-awesome "${USER_PKGS[*]}")" \
686 ttf-hack "A hand groomed typeface based on Bitstream Vera Mono" "$(ofn ttf-hack "${USER_PKGS[*]}")" \
687 vlc "A free and open source cross-platform multimedia player" "$(ofn vlc "${USER_PKGS[*]}")" \
688 weechat "Fast, light and extensible IRC client" "$(ofn weechat "${USER_PKGS[*]}")" \
689 xarchiver "A GTK+ frontend to various command line archivers" "$(ofn xarchiver "${USER_PKGS[*]}")" \
690 xfce-terminal "A terminal emulator based in the Xfce Desktop Environment" "$(ofn xfce-terminal "${USER_PKGS[*]}")" \
691 xterm "The standard terminal emulator for the X window system" "$(ofn xterm "${USER_PKGS[*]}")" \
692 zathura "Minimalistic document viewer" "$(ofn zathura "${USER_PKGS[*]}")"
694 if [[ $USER_PKGS ]]; then
695 for i in $USER_PKGS; do
696 [[ ${PKG_EXT[$i]} && $USER_PKGS != *"${PKG_EXT[$i]}"* ]] && USER_PKGS+=" ${PKG_EXT[$i]}"
703 ###############################################################################
708 check_background_install || return 0
709 local device choice devhash
710 devhash="$(lsblk -f | base64)"
712 part_device || return 1
717 if [[ $DISPLAY && $TERM != 'linux' ]] && hash gparted >/dev/null 2>&1; then
718 dlg choice menu "Edit Partitions" "$_part" \
719 "auto" "Whole device automatic partitioning" \
720 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
721 "gparted" "GUI front end to parted" \
722 "cfdisk" "Curses based variant of fdisk" \
723 "parted" "GNU partition editor" \
724 "fdisk" "Dialog-driven creation and manipulation of partitions" \
725 "done" "Return to the main menu" || return 0
727 dlg choice menu "Edit Partitions" "$_part" \
728 "auto" "Whole device automatic partitioning" \
729 "shrink" "Shrink an existing ext2/3/4 or ntfs partition to make room for a new partition" \
730 "cfdisk" "Curses based variant of fdisk" \
731 "parted" "GNU partition editor" \
732 "fdisk" "Dialog-driven creation and manipulation of partitions" \
733 "done" "Return to the main menu" || return 0
736 if [[ $choice == 'done' ]]; then
738 elif [[ $choice == 'shrink' ]]; then
739 part_shrink "$device"
740 elif [[ $choice == 'auto' ]]; then
741 local root_size txt table boot_fs
742 root_size=$(lsblk -lno SIZE "$device" | awk 'NR == 1 {
745 print ($1 * 1000 - 512) / 1000 "G"
751 txt="\nWARNING:\n\nALL data on $device will be destroyed and the following partitions will be created\n\n- "
752 if [[ $SYS == 'BIOS' ]]; then
753 table="msdos" boot_fs="ext4"
754 txt+="An $boot_fs boot partition with the boot flag enabled (512M)\n- "
756 table="gpt" boot_fs="fat32"
757 txt+="A $boot_fs efi boot partition (512M)\n- "
759 txt+="An ext4 partition using all remaining space ($root_size)\n\nDo you want to continue?\n"
760 yesno "Auto Partition" "$txt" && part_auto "$device" "$table" "$boot_fs" "$root_size"
766 if [[ $devhash != "$(lsblk -f | base64)" ]]; then
767 msg "Probing Partitions" "\nInforming the kernel of partition changes using partprobe.\n" 0
768 partprobe >/dev/null 2>&1
776 if [[ $IGNORE_DEV ]]; then
777 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk "!/$IGNORE_DEV/"' && /disk|part|lvm|crypt|NAME/')"
779 txt="$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINT | awk '/disk|part|lvm|crypt|NAME/')"
781 msg "Device Tree" "\n\n$txt\n\n"
786 if [[ $1 == "$MNT/swapfile" && $SWAP_SIZE ]]; then
787 fallocate -l $SWAP_SIZE "$1" 2>$ERR
788 errshow "fallocate -l $SWAP_SIZE $1"
789 chmod 600 "$1" 2>$ERR
790 errshow "chmod 600 $1"
792 mkswap "$1" >/dev/null 2>$ERR
794 swapon "$1" >/dev/null 2>$ERR
801 local device="$1" table="$2" boot_fs="$3" size="$4" dev_info=""
802 dev_info="$(parted -s "$device" print)"
804 msg "Auto Partition" "\nRemoving partitions on $device and setting table to $table\n" 1
807 while read -r PART; do
808 parted -s "$device" rm "$PART" >/dev/null 2>&1
809 done <<< "$(awk '/^ [1-9][0-9]?/ {print $1}' <<< "$dev_info" | sort -r)"
811 [[ $(awk '/Table:/ {print $3}' <<< "$dev_info") != "$table" ]] && parted -s "$device" mklabel "$table" >/dev/null 2>&1
813 msg "Auto Partition" "\nCreating a 512M $boot_fs boot partition.\n" 1
814 if [[ $SYS == "BIOS" ]]; then
815 parted -s "$device" mkpart primary "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
817 parted -s "$device" mkpart ESP "$boot_fs" 1MiB 513MiB >/dev/null 2>&1
822 AUTO_BOOT_PART=$(lsblk -lno NAME,TYPE "$device" | awk 'NR==2 {print "/dev/" $1}')
824 if [[ $SYS == "BIOS" ]]; then
825 mkfs.ext4 -q "$AUTO_BOOT_PART" >/dev/null 2>&1
827 mkfs.vfat -F32 "$AUTO_BOOT_PART" >/dev/null 2>&1
830 msg "Auto Partition" "\nCreating a $size ext4 root partition.\n" 0
831 parted -s "$device" mkpart primary ext4 513MiB 100% >/dev/null 2>&1
833 AUTO_ROOT_PART="$(lsblk -lno NAME,TYPE "$device" | awk 'NR==3 {print "/dev/" $1}')"
834 mkfs.ext4 -q "$AUTO_ROOT_PART" >/dev/null 2>&1
836 FORMATTED+="$AUTO_BOOT_PART $AUTO_ROOT_PART "
837 msg "Auto Partition" "\nProcess complete.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$device")\n"
842 local regexp="$1" err=''
844 # string of partitions as /TYPE/PART SIZE
845 if [[ $IGNORE_DEV ]]; then
846 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
847 awk "/$regexp/"' && !'"/$IGNORE_DEV/"' {
848 sub(/^part/, "/dev/")
849 sub(/^lvm|^crypt/, "/dev/mapper/")
853 PARTS="$(lsblk -lno TYPE,NAME,SIZE |
855 sub(/^part/, "/dev/")
856 sub(/^lvm|^crypt/, "/dev/mapper/")
861 # number of partitions total
863 while read -r line; do
867 # ensure we have enough partitions for the system and action type
869 'part|lvm|crypt') [[ $COUNT -lt 1 || ($SYS == 'UEFI' && $COUNT -lt 2) ]] && err="$_errpart" ;;
870 'part|crypt') (( COUNT < 1 )) && err="$_lvmerr" ;;
871 'part|lvm') (( COUNT < 2 )) && err="$_lukserr" ;;
874 # if there aren't enough partitions show the relevant error message
875 [[ $err ]] && { msg "Not Enough Partitions" "$err" 2; return 1; }
882 local part="$1" mountp="${MNT}$2" fs=""
883 fs="$(lsblk -lno FSTYPE "$part")"
886 if [[ $fs && ${FS_OPTS[$fs]} && $part != "$BOOT_PART" ]] && select_mntopts "$fs"; then
887 mount -o "$MNT_OPTS" "$part" "$mountp" >/dev/null 2>&1
889 mount "$part" "$mountp" >/dev/null 2>&1
892 part_mountconf "$part" "$mountp" || return 1
900 local part="$1" fs="$2" delay="$3"
902 msg "Format" "\nFormatting $part as $fs\n" 0
903 ${FS_CMDS[$fs]} "$part" >/dev/null 2>$ERR
904 errshow "${FS_CMDS[$fs]} $part" || return 1
913 local device="$1" fs=""
915 part_find "${device##*/}[^ ]" || return 1
916 (( COUNT == 1 )) && part="$(awk '{print $1}' <<< "${PARTS[@]}" )"
918 if (( COUNT == 1 )) || dlg part menu "Resize" "\nWhich partition on $device do you want to resize?" $PARTS && [[ $part ]]; then
919 fs=$(lsblk -lno FSTYPE "$part")
922 msg "Resize" "\nGathering device size info.\n" 0
924 # get device size info
926 end=$(parted -s "$device" unit KiB print | awk '/^\s*'"$num"'/ {print int($3)}') # part size in KiB
927 devsize=$(parted -s "$device" unit KiB print | awk '/Disk '"${device//\//\\/}"':/ {print int($3)}') # whole device size in KiB
929 # minimum in KiB (2^10)
931 ext[2-4]) min=$(dumpe2fs -h "$part" |& awk '/Block count/{count=$NF} /Block size/{size=$NF} END{print int((count * size) / 1024)}') ;;
932 ntfs) min=$(ntfsresize -f -m "$part" | awk 'NR == 2 {print int(($NF * 1000 * 1000) / 1024)}') ;;
936 mbmin=$((min / 1024))
937 mbend=$((end / 1024))
939 # get new size from user
941 if dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " Resize: $part " --rangebox "$_resize" 17 "$COLUMNS" "$mbmin" "$mbend" $((mbend / 2)) 2>$ANS; then
942 (( (size = $(< "$ANS")) < mbend )) || return 1
943 size=$((size * 1024))
951 e2fsck -f "$part"; sleep 0.5
952 resize2fs -f "$part" ${size}K 2>$ERR # K=2^10 bytes
953 errshow "resize2fs -f $part ${size}K" || return 1
956 ntfsresize -fc "$part" || { 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"; return 1; }
957 ntfsresize -ff --size $(( (size * 1024) / 1000 ))k "$part" 2>$ERR # k=10^3 bytes
958 errshow "ntfsresize -f -s $(( (size * 1024) / 1000 ))k $part" || return 1
962 echo "filesystem shrunk successfully, now the partition"
964 parted "$device" resizepart "$num" ${size}KiB || return 1
968 if [[ $devsize == "$end" ]]; then
969 parted -s "$device" mkpart primary ext4 ${size}KiB 100% 2>$ERR
970 errshow "parted -s $device mkpart primary ext4 ${size}KiB 100%" || return 1
972 parted -s "$device" mkpart primary ext4 ${size}KiB ${end}KiB 2>$ERR
973 errshow "parted -s $device mkpart primary ext4 ${size}KiB ${end}KiB" || return 1
976 msg "Resize Complete" "\n$part has been successfully resized to $((size / 1024))M.\n"
978 *) msg "Invalid Filesystem: $fs" "\nResizing only supports ext and ntfs.\n\nFor unformatted partitions, cfdisk can be used.\n" ;;
985 if [[ $DEV_COUNT -eq 1 && $SYS_DEVS ]]; then
986 DEVICE="$(awk '{print $1}' <<< "$SYS_DEVS")"
987 elif (( DEV_COUNT > 1 )); then
989 dlg DEVICE menu "Boot Device" "\nSelect the device to use for bootloader install." $SYS_DEVS
991 dlg DEVICE menu "Select Device" "$_device" $SYS_DEVS
993 [[ $DEVICE ]] || return 1
994 elif [[ $DEV_COUNT -lt 1 && ! $1 ]]; then
995 msg "Device Error" "\nNo available devices.\n\nExiting..\n" 2; die 1
998 [[ $1 ]] && BOOT_DEV="$DEVICE"
1005 BOOT_DEV="${BOOT_PART%[1-9]}"
1006 BOOT_PART_NUM="${BOOT_PART: -1}"
1007 [[ $BOOT_PART = /dev/nvme* ]] && BOOT_DEV="${BOOT_PART%p[1-9]}"
1008 if [[ $SYS == 'UEFI' ]]; then
1009 parted -s $BOOT_DEV set $BOOT_PART_NUM esp on >/dev/null 2>&1
1011 parted -s $BOOT_DEV set $BOOT_PART_NUM boot on >/dev/null 2>&1
1018 local part="$1" devs=""
1019 devs="$(lsblk -lno NAME,FSTYPE,TYPE)"
1021 # Identify if $part is LUKS+LVM, LVM+LUKS, LVM alone, or LUKS alone
1022 if lsblk -lno TYPE "$part" | grep -q 'crypt'; then
1024 LUKS_NAME="${part#/dev/mapper/}"
1026 for dev in $(awk '/lvm/ && /crypto_LUKS/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1027 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1028 LUKS_DEV="$LUKS_DEV cryptdevice=$dev:$LUKS_NAME"
1029 LVM='logical volume'
1034 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1035 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1036 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1037 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1042 elif lsblk -lno TYPE "$part" | grep -q 'lvm'; then
1043 LVM='logical volume'
1044 VNAME="${part#/dev/mapper/}"
1046 for dev in $(awk '/crypt/ && /lvm2_member/ {print "/dev/mapper/"$1}' <<< "$devs" | uniq); do
1047 if lsblk -lno NAME "$dev" | grep -q "$VNAME"; then
1048 LUKS_NAME="${dev/\/dev\/mapper\//}"
1053 for dev in $(awk '/part/ && /crypto_LUKS/ {print "/dev/"$1}' <<< "$devs" | uniq); do
1054 if lsblk -lno NAME "$dev" | grep -q "$LUKS_NAME"; then
1055 LUKS_UUID="$(lsblk -lno UUID,TYPE,FSTYPE "$dev" | awk '/part/ && /crypto_LUKS/ {print $1}')"
1056 LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
1067 if (( COUNT > 0 )); then
1068 PARTS="$(sed "/${i//\//\\/}/d" <<< "$PARTS")"
1076 if grep -qw "$1" /proc/mounts; then
1077 msg "Mount Success" "\nPartition $1 mounted at $2\n" 1
1081 msg "Mount Fail" "\nPartition $1 failed to mount at $2\n" 2
1086 ###############################################################################
1091 check_background_install || return 0
1094 part_find 'part|lvm|crypt' || { SEL=2; return 1; }
1096 [[ $LUKS && $LUKS_PART ]] && part_countdec $LUKS_PART
1097 [[ $LVM && $LVM_PARTS ]] && part_countdec $LVM_PARTS
1099 select_root_partition || return 1
1101 if [[ $SYS == 'UEFI' ]]; then
1102 select_efi_partition || { BOOT_PART=''; return 1; }
1103 elif (( COUNT > 0 )); then
1104 select_boot_partition || { BOOT_PART=''; return 1; }
1107 if [[ $BOOT_PART ]]; then
1108 part_mount "$BOOT_PART" "/$BOOTDIR" && SEP_BOOT=true || return 1
1112 select_swap || return 1
1113 select_extra_partitions || return 1
1114 install_background || return 1
1121 dlg SWAP_PART menu "Swap Setup" "\nSelect whether to use a swapfile, swap partition, or none." \
1122 "none" "Don't allocate any swap space" \
1123 "swapfile" "Allocate $SYS_MEM at /swapfile" \
1126 if [[ -z $SWAP_PART || $SWAP_PART == "none" ]]; then
1129 elif [[ $SWAP_PART == "swapfile" ]]; then
1131 until [[ ${SWAP_SIZE:0:1} =~ [1-9] && ${SWAP_SIZE: -1} =~ (M|G) ]]; do
1132 (( 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
1133 dlg SWAP_SIZE input "Swap Setup" "$_swapsize" "$SYS_MEM" || { SWAP_PART=''; SWAP_SIZE=''; return 1; }
1136 part_swap "$MNT/$SWAP_PART"
1137 SWAP_PART="/$SWAP_PART"
1138 elif [[ $PARTS == *"$SWAP_PART"* ]]; then
1139 part_swap $SWAP_PART
1140 part_countdec $SWAP_PART
1141 SWAP_SIZE="$(lsblk -lno SIZE $SWAP_PART)"
1151 local fs="$1" opts=''
1152 local title="${fs^} Mount Options"
1154 for i in ${FS_OPTS[$fs]}; do
1158 until [[ $MNT_OPTS ]]; do
1159 dlg MNT_OPTS check "$title" "$_mount" $opts
1160 [[ $MNT_OPTS ]] || return 1
1161 MNT_OPTS="${MNT_OPTS// /,}"
1162 yesno "$title" "\nConfirm the following options: $MNT_OPTS\n" || MNT_OPTS=''
1171 until [[ $EXMNT ]]; do
1172 dlg EXMNT input "Extra Mount $part" "$_exmnt" "/" || return 1
1173 if [[ ${EXMNT:0:1} != "/" || ${#EXMNT} -le 1 || $EXMNT =~ \ |\' || $EXMNTS == *"$EXMNT"* ]]; then
1174 msg "Mountpoint Error" "$_errexpart"
1183 local part="$1" fs='' cur=''
1184 local txt="\nSelect which filesystem to use for: $part\n\nDefault: ext4"
1185 cur="$(lsblk -lno FSTYPE "$part" 2>/dev/null)"
1188 if [[ $cur && ($part != "$ROOT_PART" || $FORMATTED == *"$part"*) ]]; then
1189 dlg fs menu "Filesystem" "$txt\nCurrent: $cur" skip - ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1191 dlg fs menu "Filesystem" "$txt" ext4 - ext3 - ext2 - vfat - ntfs - f2fs - jfs - xfs - nilfs2 - reiserfs - || return 1
1193 [[ $fs == 'skip' ]] && return 0
1194 yesno "Filesystem" "\nFormat $part as $fs?\n" || fs=''
1196 part_format "$part" "$fs"
1199 select_efi_partition()
1201 if (( COUNT == 1 )); then
1202 BOOT_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
1203 elif [[ $AUTO_BOOT_PART ]]; then
1204 BOOT_PART="$AUTO_BOOT_PART"
1205 return 0 # were done here
1207 dlg BOOT_PART menu "EFI Partition" "$_uefi" $PARTS
1210 [[ $BOOT_PART ]] || return 1
1212 if grep -q 'fat' <<< "$(fsck -N "$BOOT_PART")"; then
1213 local txt="\nIMPORTANT:\n\nThe EFI partition $BOOT_PART $_format"
1214 if yesno "Format EFI Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1215 part_format "$BOOT_PART" "vfat" 2
1218 part_format "$BOOT_PART" "vfat" 2
1224 select_boot_partition()
1226 if [[ $AUTO_BOOT_PART && ! $LVM ]]; then
1227 BOOT_PART="$AUTO_BOOT_PART"; return 0 # were done here
1228 elif [[ $LUKS && ! $LVM ]]; then
1229 dlg BOOT_PART menu "Boot Partition" "$_biosluks" $PARTS
1230 [[ $BOOT_PART ]] || return 1
1232 dlg BOOT_PART menu "Boot Partition" "$_bios" "skip" "don't use a separate boot" $PARTS
1233 [[ -z $BOOT_PART || $BOOT_PART == "skip" ]] && { BOOT_PART=''; return 0; }
1236 if grep -q 'ext[34]' <<< "$(fsck -N "$BOOT_PART")"; then
1237 local txt="\nIMPORTANT:\n\nThe boot partition $BOOT_PART $_format"
1238 if yesno "Format Boot Partition" "$txt" "Format $BOOT_PART" "Skip Formatting" 1; then
1239 part_format "$BOOT_PART" "ext4" 2
1242 part_format "$BOOT_PART" "ext4" 2
1247 select_root_partition()
1249 if [[ $AUTO_ROOT_PART && -z $LVM && -z $LUKS ]]; then
1250 ROOT_PART="$AUTO_ROOT_PART"
1251 elif (( COUNT == 1 )); then
1252 ROOT_PART="$(awk 'NR==1 {print $1}' <<< "$PARTS")"
1254 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." $PARTS
1256 [[ $ROOT_PART ]] || return 1
1258 select_filesystem "$ROOT_PART" || { ROOT_PART=''; return 1; }
1259 part_mount "$ROOT_PART" || { ROOT_PART=''; return 1; }
1264 select_extra_partitions()
1267 while (( COUNT > 0 )); do
1269 dlg part menu 'Mount Extra' "$_expart" 'done' 'finish mounting step' $PARTS || break
1270 if [[ $part == 'done' ]]; then
1272 elif select_filesystem "$part" && select_mountpoint && part_mount "$part" "$EXMNT"; then
1273 EXMNTS+="$part: $EXMNT "
1274 [[ $EXMNT == '/usr' && $HOOKS != *usr* ]] && HOOKS="usr $HOOKS"
1282 ###############################################################################
1290 genfstab -U $MNT >$MNT/etc/fstab 2>$ERR
1291 errshow 1 "genfstab -U $MNT >$MNT/etc/fstab"
1292 [[ -f $MNT/swapfile ]] && sed -i "s~${MNT}~~" $MNT/etc/fstab
1296 chrun "hwclock --systohc --utc" || chrun "hwclock --systohc --utc --directisa"
1299 chrun "chown -Rf $NEWUSER:users /home/$NEWUSER"
1303 dlg choice menu "Finalization" "$_edit" \
1304 finished "exit the installer and reboot" \
1305 keyboard "${EDIT_FILES[keyboard]}" \
1306 console "${EDIT_FILES[console]}" \
1307 locale "${EDIT_FILES[locale]}" \
1308 hostname "${EDIT_FILES[hostname]}" \
1309 sudoers "${EDIT_FILES[sudoers]}" \
1310 mkinitcpio "${EDIT_FILES[mkinitcpio]}" \
1311 fstab "${EDIT_FILES[fstab]}" \
1312 crypttab "${EDIT_FILES[crypttab]}" \
1313 bootloader "${EDIT_FILES[bootloader]}" \
1314 pacman "${EDIT_FILES[pacman]}" \
1315 login "${EDIT_FILES[login]}"
1317 if [[ -z $choice || $choice == 'finished' ]]; then
1318 [[ $DEBUG == true && -r $DBG ]] && vim $DBG
1322 for f in ${EDIT_FILES[$choice]}; do
1323 [[ -e ${MNT}$f ]] && exists+=" ${MNT}$f"
1325 if [[ $exists ]]; then
1328 msg "File Missing" "\nThe file(s) selected do not exist:\n\n${EDIT_FILES[$choice]}\n"
1336 if [[ $RSYNC_PID || $MIRROR_PID ]]; then
1337 while kill -0 "$RSYNC_PID" 2>/dev/null || kill -0 "$MIRROR_PID" 2>/dev/null; do
1338 clear; printf "\nOne or more background install processes are still running...\n"; sleep 1
1341 unset RSYNC_PID MIRROR_PID
1342 elif [[ -d /run/archiso/sfs/airootfs/etc/skel ]]; then
1343 rsync -ahv /run/archiso/sfs/airootfs/ $MNT/ 2>$ERR
1344 errshow 1 "rsync -ahv /run/archiso/sfs/airootfs/ $MNT/"
1345 install_mirrorlist "$MNT/etc/pacman.d/mirrorlist"
1346 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1348 mkdir -p /etc/pacman.d/mirrorlist
1349 install_mirrorlist "/etc/pacman.d/mirrorlist"
1350 pacstrap $MNT base $ISO_BASE 2>$ERR
1351 errshow 1 "pacstrap $MNT base $KERNEL $ISO_BASE"
1352 mkdir -p $MNT/etc/pacman.d/mirrorlist
1353 cp -f "/etc/pacman.d/mirrorlist" "$MNT/etc/pacman.d/mirrorlist"
1354 chrun "pacman -Syyu --noconfirm && pacman -S $BASE_PKGS --needed --noconfirm"
1357 rm -rf $MNT/etc/mkinitcpio-archiso.conf
1358 find $MNT/usr/lib/initcpio -name 'archiso*' -type f -delete
1359 sed -i 's/volatile/auto/g' $MNT/etc/systemd/journald.conf
1360 find $MNT/boot -name '*-ucode.img' -delete
1363 find $MNT/etc/X11/xorg.conf.d/ -name '*.conf' -delete
1364 elif lspci | grep ' VGA ' | grep -q 'Intel'; then
1365 cat > $MNT/etc/X11/xorg.conf.d/20-intel.conf << EOF
1367 Identifier "Intel Graphics"
1369 Option "TearFree" "true"
1374 [[ -e /run/archiso/sfs/airootfs && $KERNEL == 'linux' ]] && cp -vf $RUN/x86_64/vmlinuz $MNT/boot/vmlinuz-linux
1376 cp -fv /etc/resolv.conf $MNT/etc/
1377 [[ -e /etc/NetworkManager/system-connections ]] && cp -rvf /etc/NetworkManager/system-connections $MNT/etc/NetworkManager/
1379 echo "LANG=$MYLOCALE" > $MNT/etc/locale.conf
1380 cp -f $MNT/etc/locale.conf $MNT/etc/default/locale
1381 sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; s/#${MYLOCALE}/${MYLOCALE}/g" $MNT/etc/locale.gen
1383 chrun "ln -svf /usr/share/zoneinfo/$ZONE/$SUBZ /etc/localtime"
1385 if [[ $BROADCOM_WL ]]; then
1386 echo 'blacklist bcma' >> $MNT/etc/modprobe.d/blacklist.conf
1387 rm -f $MNT/etc/modprobe/
1390 cat > $MNT/etc/X11/xorg.conf.d/00-keyboard.conf << EOF
1391 # Use localectl(1) to instruct systemd-localed to update it.
1392 Section "InputClass"
1393 Identifier "system-keyboard"
1394 MatchIsKeyboard "on"
1395 Option "XkbLayout" "$KEYMAP"
1398 cat > $MNT/etc/default/keyboard << EOF
1399 # KEYBOARD CONFIGURATION FILE
1400 # Consult the keyboard(5) manual page.
1407 printf "KEYMAP=%s\nFONT=%s\n" "$CMAP" "$FONT" > $MNT/etc/vconsole.conf
1408 echo "$MYHOST" > $MNT/etc/hostname
1409 cat > $MNT/etc/hosts << EOF
1412 ::1 localhost ip6-localhost ip6-loopback
1413 ff02::1 ip6-allnodes
1414 ff02::2 ip6-allrouters
1420 if [[ $ROOT_PART == /dev/mapper* ]]; then
1421 ROOT_PART_ID="$ROOT_PART"
1423 local uuid_type="UUID"
1424 [[ $BOOTLDR =~ (systemd-boot|refind-efi|efistub) ]] && uuid_type="PARTUUID"
1425 ROOT_PART_ID="$uuid_type=$(blkid -s $uuid_type -o value $ROOT_PART)"
1428 if [[ $SYS == 'UEFI' ]]; then
1429 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname "$DIST" -type d -delete
1430 find $MNT/$BOOTDIR/EFI/ -maxdepth 1 -mindepth 1 -iname 'boot' -type d -delete
1434 chrun "${BCMDS[$BOOTLDR]}" 2>$ERR
1435 errshow 1 "${BCMDS[$BOOTLDR]}"
1437 if [[ -d $MNT/hostrun ]]; then
1438 umount $MNT/hostrun/udev >/dev/null 2>&1
1439 umount $MNT/hostrun/lvm >/dev/null 2>&1
1440 rm -rf $MNT/hostrun >/dev/null 2>&1
1443 if [[ $SYS == 'UEFI' ]]; then
1444 # some UEFI firmware requires a generic esp/BOOT/BOOTX64.EFI
1445 mkdir -pv $MNT/$BOOTDIR/EFI/BOOT
1446 if [[ $BOOTLDR == 'grub' ]]; then
1447 cp -fv $MNT/$BOOTDIR/EFI/$DIST/grubx64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1448 elif [[ $BOOTLDR == 'syslinux' ]]; then
1449 cp -rf $MNT/$BOOTDIR/EFI/syslinux/* $MNT/$BOOTDIR/EFI/BOOT/
1450 cp -f $MNT/$BOOTDIR/EFI/syslinux/syslinux.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1451 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1452 sed -i '/#extra_kernel_version_strings/ c extra_kernel_version_strings linux-hardened,linux-zen,linux-lts,linux' $MNT/$BOOTDIR/EFI/refind/refind.conf
1453 cp -fv $MNT/$BOOTDIR/EFI/refind/refind_x64.efi $MNT/$BOOTDIR/EFI/BOOT/BOOTX64.EFI
1462 chrun "chpasswd <<< 'root:$ROOT_PASS'" 2>$ERR
1463 errshow 1 "set root password"
1464 if [[ $MYSHELL != *zsh ]]; then
1465 chrun "usermod -s $MYSHELL root" 2>$ERR
1466 errshow 1 "usermod -s $MYSHELL root"
1467 [[ $MYSHELL == "/usr/bin/mksh" ]] && cp -fv $MNT/etc/skel/.mkshrc /root/.mkshrc
1470 local groups='audio,autologin,floppy,log,network,rfkill,scanner,storage,optical,power,wheel'
1472 chrun "groupadd -r autologin" 2>$ERR
1473 errshow 1 "groupadd -r autologin"
1474 chrun "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER" 2>$ERR
1475 errshow 1 "useradd -m -u 1000 -g users -G $groups -s $MYSHELL $NEWUSER"
1476 chrun "chpasswd <<< '$NEWUSER:$USER_PASS'" 2>$ERR
1477 errshow 1 "set $NEWUSER password"
1479 if [[ $USER_PKGS == *neovim* ]]; then
1480 mkdir -p $MNT/home/$NEWUSER/.config/nvim
1481 cp -fv $MNT/home/$NEWUSER/.vimrc $MNT/home/$NEWUSER/.config/nvim/init.vim
1482 cp -rfv $MNT/home/$NEWUSER/.vim/colors $MNT/home/$NEWUSER/.config/nvim/colors
1485 [[ $INSTALL_WMS == *dwm* ]] && install_suckless
1486 [[ $LOGIN_WM =~ (startkde|gnome-session) ]] && sed -i '/super/d' $MNT/home/$NEWUSER/.xprofile /root/.xprofile
1493 SERVICE="$MNT/etc/systemd/system/getty@tty1.service.d"
1494 sed -i '/printf/d' $MNT/root/.zshrc
1496 if [[ -e $MNT/home/$NEWUSER/.xinitrc ]] && grep -q 'exec' $MNT/home/$NEWUSER/.xinitrc; then
1497 sed -i "/exec/ c exec ${LOGIN_WM}" $MNT/home/$NEWUSER/.xinitrc
1499 printf "exec %s\n" "$LOGIN_WM" >> $MNT/home/$NEWUSER/.xinitrc
1502 [[ ${EDIT_FILES[login]} == *"$LOGINRC"* ]] || EDIT_FILES[login]+=" /home/$NEWUSER/$LOGINRC"
1504 if [[ $AUTOLOGIN ]]; then
1505 sed -i "s/root/${NEWUSER}/g" $SERVICE/autologin.conf
1506 cat > $MNT/home/$NEWUSER/$LOGINRC <<EOF
1508 # sourced by ${MYSHELL##*/} when used as a login shell
1510 # automatically run startx when logging in on tty1
1511 [[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && exec startx -- vt1
1515 rm -rf $MNT/home/$NEWUSER/.{profile,zprofile,bash_profile}
1522 local inpkg="$PACKAGES $USER_PKGS"
1524 if pacman -Qsq 'archlabs-installer' >/dev/null 2>&1; then
1525 rmpkg+=" archlabs-installer"
1526 elif [[ -e "$MNT/usr/bin/archlabs-installer" ]]; then
1527 rm -f "$MNT/usr/bin/archlabs-installer"
1530 [[ $UCODE ]] && inpkg+=" $UCODE"
1531 [[ $MYSHELL == *mksh ]] && inpkg+=" mksh"
1532 [[ $KERNEL == 'linux' ]] || { inpkg+=" $KERNEL"; rmpkg+=" linux"; }
1533 [[ $inpkg =~ (term|urxvt|tilix|alacritty|sakura|tilda|plasma|cinnamon) || $INSTALL_WMS == *dwm* ]] || inpkg+=" xterm"
1534 [[ $MYSHELL == '/usr/bin/zsh' ]] && inpkg+=" zsh-completions"
1535 [[ $INSTALL_WMS =~ ^(plasma|gnome|cinnamon)$ ]] || inpkg+=" archlabs-ksuperkey"
1536 [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps|dwm|fluxbox) ]] && inpkg+=" $WM_BASE_PKGS"
1538 chrun "pacman -Syyu --noconfirm"
1539 [[ $rmpkg ]] && chrun "pacman -Rns $rmpkg --noconfirm"
1540 chrun "pacman -S iputils --noconfirm"
1541 chrun "pacman -S $inpkg --needed --noconfirm" 2>$ERR
1542 errshow 1 "pacman -S $inpkg --needed --noconfirm"
1544 if [[ $BOOTLDR == 'grub' ]]; then
1545 if [[ $SYS == 'BIOS' ]]; then
1546 chrun "pacman -S grub os-prober --needed --noconfirm" 2>$ERR
1547 errshow 1 "pacman -S grub os-prober --needed --noconfirm"
1549 chrun "pacman -S grub os-prober efibootmgr --needed --noconfirm" 2>$ERR
1550 errshow 1 "pacman -S grub os-prober efibootmgr --needed --noconfirm"
1552 elif [[ $BOOTLDR == 'refind-efi' ]]; then
1553 chrun "pacman -S refind-efi efibootmgr --needed --noconfirm" 2>$ERR
1554 errshow 1 "pacman -S refind-efi efibootmgr --needed --noconfirm"
1555 elif [[ $SYS == 'UEFI' ]]; then
1556 chrun "pacman -S efibootmgr --needed --noconfirm" 2>$ERR
1557 errshow 1 "pacman -S efibootmgr --needed --noconfirm"
1559 sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" $MNT/etc/sudoers
1565 mkdir -pv $MNT/home/$NEWUSER/suckless
1567 for i in dwm dmenu st; do
1568 if chrun "git clone https://git.suckless.org/$i /home/$NEWUSER/suckless/$i"; then
1569 chrun "cd /home/$NEWUSER/suckless/$i; make PREFIX=/usr install; make clean; rm config.h"
1571 printf "failed to clone %s repo\n" "$i"
1575 if [[ -d $MNT/home/$NEWUSER/suckless/dwm && -x $MNT/usr/bin/dwm ]]; then
1576 printf "To configure dwm edit %s\n" "/home/$NEWUSER/suckless/dwm/config.h"
1577 printf "You can then recompile it with 'sudo make clean install'\n"
1582 install_mkinitcpio()
1586 # luks keyfile creation
1587 # currently not used due to not prompting for passphrase on startup
1588 # [[ $LUKS_UUID && $LUKS_PASS && $SYS == 'UEFI' && $BOOTLDR == 'grub' ]] && luks_keyfile
1590 [[ $LUKS ]] && add="encrypt"
1591 [[ $LVM ]] && { [[ $add ]] && add+=" lvm2" || add+="lvm2"; }
1592 sed -i "s/block filesystems/block ${add} filesystems ${HOOKS}/g" $MNT/etc/mkinitcpio.conf
1593 chrun "mkinitcpio -p $KERNEL" 2>$ERR
1594 errshow 1 "mkinitcpio -p $KERNEL"
1597 install_mirrorlist()
1601 if hash reflector >/dev/null 2>&1; then
1602 reflector --score 120 -l 50 -f 5 --sort rate --save "$mfile"
1603 elif hash rankmirrors >/dev/null 2>&1; then
1604 i="$(json 'ip' "check&?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=ip")"
1605 c="$(json 'country_code' "${i}?access_key=5f29642060ab983b31fdf4c2935d8c56&fields=country_code")"
1606 if [[ $c && $c =~ (CA|US) ]]; then
1607 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&use_mirror_status=on"
1609 m="https://www.archlinux.org/mirrorlist/?country=${c}&use_mirror_status=on"
1611 m="https://www.archlinux.org/mirrorlist/?country=US&country=CA&country=NZ&country=GB&country=AU&use_mirror_status=on"
1613 curl -s "$m" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -t -n 10 - | tail -n 10 >"$mfile"
1618 install_background()
1620 if [[ -d /run/archiso/sfs/airootfs/etc/skel ]] && grep -qw "$MNT" /proc/mounts && (grep -qw "$MNT/$BOOTDIR" /proc/mounts || [[ $SYS == 'BIOS' && -z $LUKS ]]); then
1621 yesno "Background Install" "\nSome parts of the install can be done in the background now, base unpack, mirrorlist sort, system update, and base packages.\n\nDo you want to start the background process?\n" || return 0
1622 rsync -a /run/archiso/sfs/airootfs/ $MNT/ &
1624 ( install_mirrorlist "$MNT/etc/pacman.d/mirrorlist" && chrun "pacman -Syyu $BASE_PKGS --needed --noconfirm" ) >/dev/null 2>&1 &
1626 trap "kill $RSYNC_PID 2>/dev/null; kill $MIRROR_PID 2>/dev/null" EXIT
1631 ###############################################################################
1636 EDIT_FILES[bootloader]="/etc/default/grub"
1638 if [[ $SYS == 'BIOS' ]]; then
1639 [[ $BOOT_DEV ]] || { part_device 1 || return 1; }
1640 BCMDS[grub]="grub-install --recheck --force --target=i386-pc $BOOT_DEV"
1642 if [[ $ROOT_PART == */dev/mapper/* && -z $LVM && -z $LUKS_PASS ]]; then
1643 luks_pass "$_luksopen" 1 || return 1
1645 BCMDS[grub]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1646 grub-install --recheck --force --target=x86_64-efi --efi-directory=/$BOOTDIR --bootloader-id=$DIST"
1647 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1650 BCMDS[grub]="mkdir -p /run/udev /run/lvm &&
1651 mount --bind /hostrun/udev /run/udev &&
1652 mount --bind /hostrun/lvm /run/lvm &&
1654 grub-mkconfig -o /boot/grub/grub.cfg &&
1655 sleep 1 && umount /run/udev /run/lvm"
1662 sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g;
1663 s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $MNT/etc/default/grub
1665 if [[ $LUKS_DEV ]]; then
1666 sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1667 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $MNT/etc/default/grub 2>$ERR
1668 errshow 1 "sed -i 's~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g;
1669 s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g' $MNT/etc/default/grub"
1672 if [[ $SYS == 'BIOS' && $LVM && -z $SEP_BOOT ]]; then
1673 sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $MNT/etc/default/grub 2>$ERR
1674 errshow 1 "sed -i 's/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g' $MNT/etc/default/grub"
1677 # setup for os-prober module
1678 mkdir -p /run/{lvm,udev}
1679 mkdir -p $MNT/hostrun/{lvm,udev}
1680 mount --bind /run/lvm $MNT/hostrun/lvm
1681 mount --bind /run/udev $MNT/hostrun/udev
1688 EDIT_FILES[bootloader]=""
1693 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1694 efibootmgr -v -d $BOOT_DEV -p $BOOT_PART_NUM -c -L '${DIST} Linux' -l /vmlinuz-${KERNEL} \
1695 -u 'root=$ROOT_PART_ID rw $([[ $UCODE ]] && printf 'initrd=\%s.img ' "$UCODE")initrd=\initramfs-${KERNEL}.img'"
1701 if [[ $SYS == 'BIOS' ]]; then
1702 EDIT_FILES[bootloader]="/boot/syslinux/syslinux.cfg"
1704 EDIT_FILES[bootloader]="/boot/EFI/syslinux/syslinux.cfg"
1705 BCMDS[syslinux]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1706 efibootmgr -v -c -d $BOOT_DEV -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST"
1713 local c="$MNT/boot/syslinux" s="/usr/lib/syslinux/bios" d=".."
1714 [[ $SYS == 'UEFI' ]] && { c="$MNT/boot/EFI/syslinux"; s="/usr/lib/syslinux/efi64/"; d=''; }
1716 mkdir -pv "$c" && cp -rfv $s/* "$c/" && cp -f "$RUN/syslinux/splash.png" "$c/"
1717 cat > "$c/syslinux.cfg" << EOF
1719 MENU TITLE $DIST Boot Menu
1720 MENU BACKGROUND splash.png
1724 # see: https://www.syslinux.org/wiki/index.php/Comboot/menu.c32
1733 MENU HELPMSGENDROW 29
1734 MENU COLOR border 30;44 #40ffffff #a0000000 std
1735 MENU COLOR title 1;36;44 #9033ccff #a0000000 std
1736 MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
1737 MENU COLOR unsel 37;44 #50ffffff #a0000000 std
1738 MENU COLOR help 37;40 #c0ffffff #a0000000 std
1739 MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
1740 MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
1741 MENU COLOR msg07 37;40 #90ffffff #a0000000 std
1742 MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
1745 MENU LABEL $DIST Linux
1746 LINUX $d/vmlinuz-$KERNEL
1747 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1748 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL.img
1750 LABEL ${DIST}fallback
1751 MENU LABEL $DIST Linux Fallback
1752 LINUX $d/vmlinuz-$KERNEL
1753 APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1754 INITRD $([[ $UCODE ]] && printf "%s" "$d/$UCODE.img,")$d/initramfs-$KERNEL-fallback.img
1755 $([[ $SYS == 'BIOS' ]] && printf "\n%s" "# examples of chainloading other bootloaders
1760 #APPEND file=$d/grub/boot.img
1772 EDIT_FILES[bootloader]="/boot/refind_linux.conf"
1773 BCMDS[refind-efi]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1779 cat > $MNT/boot/refind_linux.conf << EOF
1780 "$DIST Linux" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1781 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1782 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL.img"
1783 "$DIST Linux Fallback" "root=$ROOT_PART_ID $([[ $LUKS_DEV ]] &&
1784 printf "%s " "$LUKS_DEV")rw add_efi_memmap $([[ $UCODE ]] &&
1785 printf "initrd=%s " "/$UCODE.img")initrd=/initramfs-$KERNEL-fallback.img"
1787 mkdir -p $MNT/etc/pacman.d/hooks
1788 cat > $MNT/etc/pacman.d/hooks/refind.hook << EOF
1795 Description = Updating rEFInd on ESP
1796 When = PostTransaction
1797 Exec = /usr/bin/refind-install
1801 setup_systemd-boot()
1803 EDIT_FILES[bootloader]="/boot/loader/entries/$DIST.conf"
1804 BCMDS[systemd-boot]="mount -t efivarfs efivarfs /sys/firmware/efi/efivars >/dev/null 2>&1
1805 bootctl --path=/boot install"
1808 prerun_systemd-boot()
1810 mkdir -p $MNT/boot/loader/entries
1811 cat > $MNT/boot/loader/loader.conf << EOF
1816 cat > $MNT/boot/loader/entries/$DIST.conf << EOF
1818 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1819 initrd /initramfs-$KERNEL.img
1820 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1822 cat > $MNT/boot/loader/entries/$DIST-fallback.conf << EOF
1823 title $DIST Linux Fallback
1824 linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/$UCODE.img")
1825 initrd /initramfs-$KERNEL-fallback.img
1826 options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw
1828 mkdir -p $MNT/etc/pacman.d/hooks
1829 cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF
1836 Description = Updating systemd-boot
1837 When = PostTransaction
1838 Exec = /usr/bin/bootctl update
1840 systemd-machine-id-setup --root="$MNT"
1844 ###############################################################################
1849 check_background_install || return 1
1852 dlg choice menu "Logical Volume Management" "$_lvmmenu" \
1853 "$_lvmnew" "vgcreate -f, lvcreate -L -n" \
1854 "$_lvmdel" "vgremove -f" \
1855 "$_lvmdelall" "lvrmeove, vgremove, pvremove -f" \
1856 "back" "return to the main menu"
1859 "$_lvmnew") lvm_create || return 1 ;;
1860 "$_lvmdel") lvm_delgroup && yesno "$_lvmdel" "$_lvmdelask" && vgremove -f "$DEL_VG" >/dev/null 2>&1 ;;
1861 "$_lvmdelall") lvm_del_all ;;
1870 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1871 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1872 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1874 if [[ $VGROUP && $v && $pv ]]; then
1875 msg "Logical Volume Management" "\nActivating existing logical volume management (LVM).\n\n" 1
1876 modprobe dm-mod >/dev/null 2>$ERR
1877 errshow 'modprobe dm-mod'
1878 vgscan >/dev/null 2>&1
1879 vgchange -ay >/dev/null 2>&1
1885 VGROUP='' LVM_PARTS='' VGROUP_MB=0
1887 lvm_mkgroup || return 1
1888 local txt="\nThe last (or only) logical volume will automatically use all remaining space in the volume group."
1889 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
1890 [[ $VOL_COUNT ]] || return 1
1891 lvm_extra_lvs || return 1
1892 lvm_volume_name "$_lvmlvname\nNOTE: This LV will use up all remaining space in the volume group (${VGROUP_MB}MB)" || return 1
1893 lvcreate -l +100%FREE "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
1894 errshow "lvcreate -l +100%FREE $VGROUP -n $VNAME" || return 1
1895 LVM='logical volume'; sleep 0.5
1896 txt="\nDone, volume: $VGROUP-$VNAME (${VOLUME_SIZE:-${VGROUP_MB}MB}) has been created.\n"
1897 msg "$_lvmnew (LV:$VOL_COUNT)" "$txt\n$(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE $LVM_PARTS)\n"
1903 local txt="${VGROUP}: ${SIZE}$SIZE_UNIT (${VGROUP_MB}MB remaining).$_lvmlvsize"
1907 dlg VOLUME_SIZE input "$_lvmnew (LV:$VOL_COUNT)" "$txt" ''
1908 if [[ -z $VOLUME_SIZE ]]; then
1910 break # allow bailing with escape or an empty choice
1911 elif (( ${VOLUME_SIZE:0:1} == 0 )); then
1912 ERR_SIZE=1 # size values can't begin with '0'
1914 # walk the string and make sure all but the last char are digits
1915 local lv=$((${#VOLUME_SIZE} - 1))
1916 for (( i=0; i<lv; i++ )); do
1917 [[ ${VOLUME_SIZE:$i:1} =~ [0-9] ]] || { ERR_SIZE=1; break; }
1919 if (( ERR_SIZE != 1 )); then
1920 case ${VOLUME_SIZE:$lv:1} in
1921 [mMgG]) local s=${VOLUME_SIZE:0:$lv} m=$((s * 1000))
1922 case ${VOLUME_SIZE:$lv:1} in
1923 [Gg]) (( m >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - m)) ;;
1924 [Mm]) (( ${VOLUME_SIZE:0:$lv} >= VGROUP_MB )) && ERR_SIZE=1 || VGROUP_MB=$((VGROUP_MB - s)) ;;
1931 if (( ERR_SIZE )); then
1932 msg "Invalid Logical Volume Size" "$_lvmerrlvsize"
1944 local txt="\nConfirm creation of volume group: $VGROUP\n\nwith the following partition(s):"
1946 until [[ $named ]]; do
1947 lvm_partitions || return 1
1948 lvm_group_name || return 1
1949 yesno "$_lvmnew" "$txt $LVM_PARTS\n" && named=true
1952 vgcreate -f "$VGROUP" $LVM_PARTS >/dev/null 2>$ERR
1953 errshow "vgcreate -f $VGROUP $LVM_PARTS" || return 1
1955 SIZE=$(vgdisplay "$VGROUP" | awk '/VG Size/ { gsub(/[^0-9.]/, ""); print int($0) }')
1956 SIZE_UNIT="$(vgdisplay "$VGROUP" | awk '/VG Size/ { print substr($NF, 0, 1) }')"
1958 if [[ $SIZE_UNIT == 'G' ]]; then
1959 VGROUP_MB=$((SIZE * 1000))
1964 msg "$_lvmnew" "\nVolume group: $VGROUP ($SIZE $SIZE_UNIT) has been created\n"
1971 pv="$(pvs -o pv_name --noheading 2>/dev/null)"
1972 v="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
1973 VGROUP="$(vgs -o vg_name --noheading 2>/dev/null)"
1975 if [[ $VGROUP || $v || $pv ]]; then
1976 if yesno "$_lvmdelall" "$_lvmdelask"; then
1977 for i in $v; do lvremove -f "/dev/mapper/$i" >/dev/null 2>&1; done
1978 for i in $VGROUP; do vgremove -f "$i" >/dev/null 2>&1; done
1979 for i in $pv; do pvremove -f "$i" >/dev/null 2>&1; done
1983 msg "Delete LVM" "\nNo LVMs to remove...\n" 2
1993 for i in $(lvs --noheadings | awk '{print $2}' | uniq); do
1994 VOL_GROUP_LIST+="$i $(vgdisplay "$i" | awk '/VG Size/ {print $3$4}') "
1996 [[ $VOL_GROUP_LIST ]] || { msg "No Groups" "\nNo volume groups found."; return 1; }
1998 dlg DEL_VG menu "Logical Volume Management" "\nSelect volume group to delete.\n\nAll logical volumes within will also be deleted." $VOL_GROUP_LIST
2004 while (( VOL_COUNT > 1 )); do
2005 lvm_volume_name "$_lvmlvname" && get_lv_size || return 1
2006 lvcreate -L "$VOLUME_SIZE" "$VGROUP" -n "$VNAME" >/dev/null 2>$ERR
2007 errshow "lvcreate -L $VOLUME_SIZE $VGROUP -n $VNAME" || return 1
2008 msg "$_lvmnew (LV:$VOL_COUNT)" "\nDone, logical volume (LV) $VNAME ($VOLUME_SIZE) has been created.\n"
2016 part_find 'part|crypt' || return 1
2017 PARTS="$(awk 'NF > 0 {print $0 " off"}' <<< "$PARTS")"
2018 dlg LVM_PARTS check "$_lvmnew" "\nSelect the partition(s) to use for the physical volume (PV)." $PARTS
2025 until [[ $VGROUP ]]; do
2026 dlg VGROUP input "$_lvmnew" "$_lvmvgname" "mygroup"
2027 if [[ -z $VGROUP ]]; then
2029 elif [[ ${VGROUP:0:1} == "/" || $VGROUP =~ \ |\' ]] || lsblk | grep -q "$VGROUP"; then
2030 msg "LVM Name Error" "$_lvmerrvgname"
2040 local txt="$1" default="mainvolume"
2041 (( VOL_COUNT > 1 )) && default="extravolume$VOL_COUNT"
2042 until [[ $VNAME ]]; do
2043 dlg VNAME input "$_lvmnew (LV:$VOL_COUNT)" "\n$txt" "$default"
2044 if [[ -z $VNAME ]]; then
2046 elif [[ ${VNAME:0:1} == "/" || $VNAME =~ \ |\' ]] || lsblk | grep -q "$VNAME"; then
2047 msg "LVM Name Error" "$_lvmerlvname"
2054 ###############################################################################
2060 check_background_install || return 1
2061 dlg choice menu "LUKS Encryption" "$_luksmenu" \
2062 "$_luksnew" "cryptsetup -q luksFormat" \
2063 "$_luksopen" "cryptsetup open --type luks" \
2064 "$_luksadv" "cryptsetup -q -s -c luksFormat" \
2065 "back" "Return to the main menu"
2068 "$_luksnew") luks_basic || return 1 ;;
2069 "$_luksopen") luks_open || return 1 ;;
2070 "$_luksadv") luks_advanced || return 1 ;;
2078 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2080 part_find 'part|crypt|lvm' || return 1
2082 if (( COUNT == 1 )); then
2083 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2085 dlg LUKS_PART menu "$_luksopen" "\nSelect which partition to open." $PARTS
2088 [[ $LUKS_PART ]] || return 1
2090 luks_pass "$_luksopen" || return 1
2091 msg "$_luksopen" "\nOpening encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2092 cryptsetup open --type luks "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2093 errshow "cryptsetup open --type luks $LUKS_PART $LUKS_NAME" || return 1
2094 LUKS='encrypted'; luks_show
2101 local t="$1" op="$2" v='' p='' p2=''
2103 until [[ $LUKS_PASS ]]; do
2107 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " \
2108 --mixedform "\nEnter the password to decrypt $ROOT_PART\n\nThis is needed to create a keyfile." 0 0 0 \
2109 "Password:" 1 1 '' 1 11 "$COLUMNS" 0 1 \
2110 "Password2:" 2 1 '' 2 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2113 dialog --insecure --backtitle "$DIST Installer - $SYS - v$VER" --separator $'\n' --title " $t " --mixedform "$_luksomenu" 0 0 0 \
2114 "Name:" 1 1 "${LUKS_NAME:-cryptroot}" 1 7 "$COLUMNS" 0 0 \
2115 "Password:" 2 1 '' 2 11 "$COLUMNS" 0 1 \
2116 "Password2:" 3 1 '' 3 12 "$COLUMNS" 0 1 2>"$ANS" || return 1
2120 while read -r line; do
2136 if [[ -z $op && -z $n ]]; then
2137 msg "Name Empty" "\nEncrypted device name cannot be empty.\n\nPlease try again.\n" 2
2138 elif [[ -z $p || "$p" != "$p2" ]]; then
2139 [[ $op ]] || LUKS_NAME="$n"
2140 msg "Password Mismatch" "\nThe passwords entered do not match.\n\nPlease try again.\n" 2
2142 [[ $op ]] || LUKS_NAME="$n"
2153 msg "$_luksnew" "\nEncrypted partition opened and ready for mounting.\n\n$(lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE "$LUKS_PART")\n\n"
2158 modprobe -a dm-mod dm_crypt >/dev/null 2>&1
2160 part_find 'part|lvm' || return 1
2162 if [[ $AUTO_ROOT_PART ]]; then
2163 LUKS_PART="$AUTO_ROOT_PART"
2164 elif (( COUNT == 1 )); then
2165 LUKS_PART="$(awk 'NF > 0 {print $1}' <<< "$PARTS")"
2167 dlg LUKS_PART menu "$_luksnew" "\nSelect the partition you want to encrypt." $PARTS
2170 [[ $LUKS_PART ]] || return 1
2171 luks_pass "$_luksnew"
2176 luks_setup || return 1
2177 msg "$_luksnew" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2178 cryptsetup -q luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2179 errshow "cryptsetup -q luksFormat $LUKS_PART" || return 1
2180 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2181 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2182 LUKS='encrypted'; luks_show
2188 if [[ ! -e $MNT/crypto_keyfile.bin ]]; then
2189 # printf "Creating LUKS keyfile /crypto_keyfile.bin\n"
2191 n="$(lsblk -lno NAME,UUID,TYPE | awk "/$LUKS_UUID/"' && /part|crypt|lvm/ {print $1}')"
2192 local mkkey="dd bs=512 count=8 if=/dev/urandom of=/crypto_keyfile.bin"
2193 mkkey="$mkkey && chmod 000 /crypto_keyfile.bin"
2194 mkkey="$mkkey && cryptsetup luksAddKey /dev/$n /crypto_keyfile.bin <<< '$LUKS_PASS'"
2196 sed -i 's/FILES=()/FILES=(\/crypto_keyfile.bin)/g' $MNT/etc/mkinitcpio.conf 2>$ERR
2206 dlg cipher input "LUKS Encryption" "$_lukskey" "-s 512 -c aes-xts-plain64"
2207 [[ $cipher ]] || return 1
2208 msg "$_luksadv" "\nCreating encrypted partition: $LUKS_NAME\n\nDevice or volume used: $LUKS_PART\n" 0
2209 cryptsetup -q $cipher luksFormat "$LUKS_PART" <<< "$LUKS_PASS" 2>$ERR
2210 errshow "cryptsetup -q $cipher luksFormat $LUKS_PART" || return 1
2211 cryptsetup open "$LUKS_PART" "$LUKS_NAME" <<< "$LUKS_PASS" 2>$ERR
2212 errshow "cryptsetup open $LUKS_PART $LUKS_NAME" || return 1
2219 ###############################################################################
2224 [[ "$2" == *"$1"* ]] && printf "on" || printf "off"
2233 if [[ -d $MNT ]] && command cd /; then
2235 if (( exitcode == 127 )); then
2236 umount -l /run/archiso/bootmnt
2242 # restore custom linux console 0-15 colors when not rebooting
2243 if [[ $TERM == 'linux' ]]; then
2244 colors=("\e]P0191919" "\e]P1D15355" "\e]P2609960" "\e]P3FFCC66"
2245 "\e]P4255A9B" "\e]P5AF86C8" "\e]P62EC8D3" "\e]P7949494" "\e]P8191919" "\e]P9D15355"
2246 "\e]PA609960" "\e]PBFF9157" "\e]PC4E88CF" "\e]PDAF86C8" "\e]PE2ec8d3" "\e]PFE1E1E1")
2247 printf "%b" "${colors[@]}" && clear && unset col
2255 local var="$1" dialog_type="$2" title="$3" body="$4" n=0
2257 (( ($# / 2) > SHL )) && n=$SHL
2260 case "$dialog_type" in
2262 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --menu "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2265 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --checklist "$body" 0 0 $n "$@" 2>"$ANS" || return 1
2271 if [[ $1 == 'limit' ]]; then
2272 dialog --backtitle "$DIST Installer - $SYS - v$VER" --max-input 63 --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2274 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --inputbox "$body" 0 0 "$def" 2>"$ANS" || return 1
2278 [[ -s "$ANS" ]] && printf -v "$var" "%s" "$(< "$ANS")"
2283 local title="$1" body="$2"
2285 if (( $# == 3 )); then
2286 dialog --backtitle "$DIST Installer - $SYS - v$VER" --sleep "$3" --title " $title " --infobox "$body\n" 0 0
2288 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --msgbox "$body\n" 0 0
2294 curl -s "http://api.ipstack.com/$2" | python3 -c "import sys, json; print(json.load(sys.stdin)['$1'])"
2299 local title="$1" body="$2" yes='Yes' no='No'
2300 (( $# >= 3 )) && local yes="$3"
2301 (( $# >= 4 )) && local no="$4"
2303 if (( $# == 5 )); then
2304 dialog --backtitle "$DIST Installer - $SYS - v$VER" --defaultno --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2306 dialog --backtitle "$DIST Installer - $SYS - v$VER" --title " $title " --yes-label "$yes" --no-label "$no" --yesno "$body\n" 0 0
2312 arch-chroot "$MNT" bash -c "$1"
2317 export PS4='| ${BASH_SOURCE} LINE:${LINENO} FUNC:${FUNCNAME[0]:+ ${FUNCNAME[0]}()} |> '
2326 printf "\n^C caught, cleaning up...\n"
2333 if [[ $COLUMNS -ge 110 && ${#str} -gt $((COLUMNS - 30)) ]]; then
2335 i = 2; p1 = p2 = p3 = p4 = ""; p1 = $1; q = int(NF / 4)
2336 for (; i <= q; i++) { p1 = p1 " " $i }
2337 for (; i <= q * 2; i++) { p2 = p2 " " $i }
2338 for (; i <= q * 3; i++) { p3 = p3 " " $i }
2339 for (; i <= NF; i++) { p4 = p4 " " $i }
2340 printf "%s\n %s\n %s\n %s", p1, p2, p3, p4
2342 printf "%s\n" "$str"
2343 elif [[ $str ]]; then
2344 printf "%s\n" "$str"
2351 (( exit_code == 0 )) && return 0
2353 local fatal=0 err=""
2354 err="$(sed 's/[^[:print:]]//g; s/\[[0-9\;:]*\?m//g; s/==> //g; s/] ERROR:/]\nERROR:/g' "$ERR")"
2355 (( $1 == 1 )) && { fatal=1; shift; }
2356 local txt="\nThe command exited abnormally:\n\n$1\n\n"
2359 txt+="With the following message:\n\n$err\n\n"
2361 txt+="With no error message:\n\n"
2364 if (( fatal == 1 )); then
2365 txt+="Errors at this stage are fatal and the install cannot continue.\n"
2367 txt+="Errors at this stage are non-fatal and can be either fixed or ignored depending on the error.\n"
2370 msg "Install Error" "$txt"
2372 if (( fatal == 1 )); then
2373 [[ -r $DBG && $TERM == 'linux' ]] && less "$DBG"
2382 msg "Broadcom Wireless Setup" "\nDetected chipset is Broadcom BCM4352\n\nDisabling bcma/b43 modules and loading wl module.\n" 1
2383 { rmmod wl; rmmod bcma; rmmod b43; rmmod ssb; modprobe wl; depmod -a; } >/dev/null 2>&1
2389 if [[ $1 -ge 0 ]] && ! grep -qw "$MNT" /proc/mounts; then
2390 msg "Not Mounted" "\nPartition(s) must be mounted first.\n" 2
2393 elif [[ $1 -ge 1 && -z $BOOTLDR ]]; then
2394 msg "No Bootloader" "\nBootloader must be selected first.\n" 2
2397 elif [[ $1 -ge 2 && (-z $NEWUSER || -z $USER_PASS) ]]; then
2398 msg "No User" "\nA user must be created first.\n" 2
2401 elif [[ $1 -ge 3 && -z $CONFIG_DONE ]]; then
2402 msg "Not Configured" "\nSystem configuration must be done first.\n" 2
2412 [[ -d $1 ]] && umount -R "$1" >/dev/null 2>&1
2418 msg "Network Connect" "\nVerifying network connection\n" 1
2419 curl -sIN --connect-timeout 5 'https://www.archlinux.org/' | sed '1q' | grep -q '200'
2424 if chk_connect; then
2427 if hash nmtui >/dev/null 2>&1; then
2429 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1191919" "\e]P4191919"
2431 [[ $TERM == 'linux' ]] && printf "%b" "\e]P1D15355" "\e]P4255a9b"
2441 IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
2443 if [[ $IGNORE_DEV ]]; then
2444 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
2446 SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')"
2449 if [[ -z $SYS_DEVS ]]; then
2450 msg "Device Error" "\nNo available devices...\n\nExiting..\n" 2
2455 while read -r line; do
2457 done <<< "$SYS_DEVS"
2464 elif grep -q 'AuthenticAMD' /proc/cpuinfo; then
2466 elif grep -q 'GenuineIntel' /proc/cpuinfo; then
2470 modprobe -q efivarfs >/dev/null 2>&1
2472 _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."
2473 if [[ -d /sys/firmware/efi/efivars ]]; then
2475 grep -q /sys/firmware/efi/efivars /proc/mounts || mount -t efivarfs efivarfs /sys/firmware/efi/efivars
2476 _prep+="\n - An EFI boot partition mounted."
2480 _prep+="\n\nOnce finished mounting, a portion of the install can be done in the background while you continue configuring the system:\n"
2481 _prep+="\n - Choose the system bootloader.\n - Create a user and password."
2482 _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."
2485 check_background_install()
2487 [[ $RSYNC_PID || $MIRROR_PID ]] || return 0
2488 msg "Install Running" "\nA background install process is currently running.\n" 2
2492 ###############################################################################
2495 if (( UID != 0 )); then
2496 msg "Not Root" "\nThis installer must be run as root or using sudo.\n\nExiting..\n" 2
2498 elif ! grep -qwm 1 'lm' /proc/cpuinfo; then
2499 msg "Not x86_64 Architecture" "\nThis installer only supports x86_64 architectures.\n\nExiting..\n" 2
2501 elif [[ $1 =~ (-d|--debug) ]]; then
2505 # trap ^C to perform cleanup
2511 msg "Welcome to the $DIST Installer" "\nThis will help you get $DIST setup on your system.\nHaving previous GNU/Linux and shell experience will be an asset, however we try our best to keep things simple.\n\nIf you are unsure about an option, a default will be listed or\nthe first selected option will usually be the default (excluding language and timezone).\n\n\nMenu Navigation:\n\n - Select items with the arrow keys or the option number.\n - Use [Space] to toggle options and [Enter] to confirm.\n - Switch between buttons 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"
2513 select_keymap || { clear; die 0; }
2515 if lspci -vnn -d 14e4: | grep -q 'BCM4352'; then
2519 if ! net_connect; then
2520 msg "Not Connected" "\nThis installer requires an active internet connection.\n\nExiting..\n" 2
2528 # vim:fdm=marker:fmr={,}