#!/bin/bash # Load the configuration file init() { DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$DIR"/etc/setup.conf clear ; setfont Lat2-Terminus16.psfu.gz dialog --title "Welcome to Parch Linux Installer" \ --ok-label "Begin Installation" --msgbox "Navigating the installer is \ easy.\nYou may select options using the ARROW keys and SPACE or \ ENTER.\nAlternate keys may also be used: '+', '-', and TAB." 7 70 } # Proceed with installation only if there is an internet connection check_connection() { dialog --infobox "Checking internet connection..." 3 50 # Check if a web page is available if ! nc -zw1 archlinux.org 443; then dialog --title "Connect to the Internet" \ --msgbox "The installer was unable to detect a working internet \ connection. The installation media supports wired network devices on \ boot. Make sure the cable is plugged in. Wireless users should use the \ 'iwctl' command to connect to a wireless connection.\n\nOnce you have \ a working internet connection, retry running the installer." 10 80 reset ; exit 1 fi } # Check and disable any active mountpoints check_mountpoints() { if mountpoint -q /mnt; then dialog --infobox "Unmounting active mountpoints on $DISK..." 3 50 umount -R /mnt fi if free | awk '/^Swap:/ {exit !$2}'; then swapoff -a fi } # Check for LVM on the system to avoid conflicts check_lvm_status() { # Check for an existing volume group on the selected disk if vgs --noheading --nosuffix -o pv_name | grep -q "$DISK"; then vg_on_pv=$(pvs -o pv_name,vg_name | grep "$DISK" | awk '{print $2}') dialog --title "WARNING: LVM Exists on $DISK" \ --yesno "A volume group ($vg_on_pv) was detected on the selected disk \ ($DISK).\n\nIn order to proceed, the volume group ($vg_on_pv) needs to be \ removed and all data will be lost!\n\nAre you sure you want to remove the \ volume group '$vg_on_pv'?" 11 75 if [ $? -eq 0 ]; then dialog --infobox "Removing $vg_on_pv from $DISK..." 3 50 vgchange -y -an "$vg_on_pv" &> /dev/null vgremove -y "$vg_on_pv" &> /dev/null else dialog --title "ERROR: Unable to Partition $DISK" \ --msgbox "The installer can't proceed while LVM is active on \ $DISK.\n\nIf you have any active LVM devices, please make sure they are not in \ use and backup any data on the volume group before running the installer." 8 80 reset ; exit 1 fi fi # Check for a volume group with the same name on the system when creating LVM if [ "$PARTITION_LAYOUT" != "Basic" ]; then if vgs "$LVM_GROUP" &> /dev/null; then dialog --title "WARNING: LVM Volume Group Exists" \ --yesno "A volume group with the name '$LVM_GROUP' already exists on \ your system.\n\nIn order to proceed, the volume group ($LVM_GROUP) needs to be \ overwritten and all data will be lost!\n\nAre you sure you want to overwrite \ the volume group '$LVM_GROUP'?" 11 80 if [ $? -eq 0 ]; then dialog --infobox "Removing $LVM_GROUP from $DISK..." 3 50 vgchange -y -an "$LVM_GROUP" &> /dev/null vgremove -y "$LVM_GROUP" &> /dev/null else dialog --title "ERROR: Unable to Partition $DISK" \ --msgbox "The installer can't partition the disk because a volume \ group with the name '$LVM_GROUP' already exists on your system.\n\nIf you have \ any active LVM devices, please make sure they are not in use and backup any \ data on the volume group before running the installer." 9 80 reset ; exit 1 fi fi fi } # Prompt the user to set their keyboard layout set_keymap() { while true; do KEYMAP=$(dialog --title "Set the Keyboard Layout" --nocancel \ --default-item "us" --menu "Select a keymap that corresponds to your \ keyboard layout. Choose 'other' if your keymap is not listed. If you are \ unsure, the default is 'us' (United States/QWERTY).\n\nKeymap:" 22 57 10 \ "fr" "French" \ "de" "German" \ "gr" "Greek" \ "hu" "Hungarian" \ "it" "Italian" \ "pl" "Polish" \ "ru" "Russian" \ "es" "Spanish" \ "us" "United States" \ "other" "View all available keymaps" 3>&1 1>&2 2>&3) if [ "$KEYMAP" = "other" ]; then keymaps=() for map in $(localectl list-keymaps); do keymaps+=("$map" "") done KEYMAP=$(dialog --title "Set the Keyboard Layout" --cancel-label "Back" \ --menu "Select a keymap that corresponds to your keyboard layout. The \ default is 'us' (United States/QWERTY)." 30 60 25 \ "${keymaps[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then break fi else break fi done dialog --infobox "Setting keymap to $KEYMAP..." 3 50 localectl set-keymap "$KEYMAP" loadkeys "$KEYMAP" } # Prompt the user to set the system locale set_locale() { while true; do LOCALE=$(dialog --title "Set the System Locale" --nocancel \ --default-item "en_US.UTF-8" --menu "Select a locale that corresponds \ to your language and region. The locale you select will define the language \ used by the system and other region specific information. Choose 'other' if \ your language and/or region is not listed. If you are unsure, the default is \ 'en_US.UTF-8'.\n\nLocale:" 30 65 16 \ "zh_CN.UTF-8" "Chinese (Simplified)" \ "en_AU.UTF-8" "English (Australia)" \ "en_CA.UTF-8" "English (Canada)" \ "en_US.UTF-8" "English (United States)" \ "en_GB.UTF-8" "English (Great Britain)" \ "fr_FR.UTF-8" "French (France)" \ "de_DE.UTF-8" "German (Germany)" \ "it_IT.UTF-8" "Italian (Italy)" \ "ja_JP.UTF-8" "Japanese (Japan)" \ "pt_BR.UTF-8" "Portuguese (Brazil)" \ "pt_PT.UTF-8" "Portuguese (Portugal)" \ "ru_RU.UTF-8" "Russian (Russia)" \ "es_MX.UTF-8" "Spanish (Mexico)" \ "es_ES.UTF-8" "Spanish (Spain)" \ "sv_SE.UTF-8" "Swedish (Sweden)" \ "other" "View all available locales" 3>&1 1>&2 2>&3) if [ "$LOCALE" = "other" ]; then locales=() # Read each entry in /etc/locale.gen and remove comments and spaces while read -r line; do locales+=("$line" "") done < <(grep -E "^#?[a-z].*UTF-8" /etc/locale.gen | sed -e 's/#//' -e 's/\s.*$//') LOCALE=$(dialog --title "Set the System Locale" --cancel-label "Back" \ --menu "Select a locale that corresponds to your language and region. \ The locale you select will define the language used by the system and other region specific information. If you are unsure, the default is \ 'en_US.UTF-8'.\n\nLocale:" 30 65 16 \ "${locales[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then break fi else break fi done } # Prompt the user to set the system time zone set_timezone() { utc_enabled=true regions=() for region in \ $(find /usr/share/zoneinfo -mindepth 1 -maxdepth 1 -type d -printf '%f\n' \ | grep -E -v '/$|posix|right' \ | sort); do regions+=("$region" "") done regions+=("other" "") while true; do ZONE=$(dialog --title "Set the Time Zone" --nocancel \ --menu "Select your time zone.\nIf your region is not listed, select \ 'other'.\n\nTime zone:" 27 50 17 \ "${regions[@]}" 3>&1 1>&2 2>&3) if [ "$ZONE" != "other" ]; then zone_regions=() for zone_region in \ $(find /usr/share/zoneinfo/"${ZONE}" -mindepth 1 -maxdepth 1 -printf '%f\n' \ | sort); do zone_regions+=("$zone_region" "") done SUBZONE=$(dialog --title "Set the Time Zone" --cancel-label "Back" \ --menu "Select your time zone.\n\nTime zone:" 27 50 17 \ "${zone_regions[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then if [ -d /usr/share/zoneinfo/"${ZONE}/${SUBZONE}" ]; then subzone_regions=() for subzone_region in \ $(find /usr/share/zoneinfo/"${ZONE}/${SUBZONE}" -mindepth 1 -maxdepth 1 -printf '%f\n' \ | sort); do subzone_regions+=("$subzone_region" "") done SUBZONE_SUBREGION=$(dialog --title "Set the Time Zone" \ --cancel-label "Back" \ --menu "Select your time zone.\n\nTime zone:" 27 50 17 \ "${subzone_regions[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then ZONE="${ZONE}/${SUBZONE}/${SUBZONE_SUBREGION}" break fi else ZONE="${ZONE}/${SUBZONE}" break fi fi else for other_region in \ $(find /usr/share/zoneinfo -mindepth 1 -maxdepth 1 -type f -printf '%f\n' \ | grep -E -v '/$|iso3166.tab|leapseconds|posixrules|tzdata.zi|zone.tab|zone1970.tab' \ | sort); do other_regions+=("$other_region" "") done ZONE=$(dialog --title "Set the Time Zone" --cancel-label "Back" \ --menu "Select your time zone.\n\nTime zone:" 27 50 17 \ "${other_regions[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then ZONE="${ZONE}" break fi fi done dialog --title "Set the Hardware Clock" --nocancel \ --yesno "Would you like to set the hardware clock from the system \ clock using UTC time?\nIf you select no, local time will be used \ instead.\n\nIf you are unsure, UTC time is the default." 8 85 if [ $? -ne 0 ]; then utc_enabled=false fi } # Prompt the user to set the system hostname set_hostname() { while true; do HOST_NAME=$(dialog --title "Set the Hostname" --nocancel \ --inputbox "Please enter the hostname for this system.\n\nThe hostname \ is a single word that identifies your system to the network.\n\nHostname:" \ 12 80 "Parch" 3>&1 1>&2 2>&3) # Hostname must be alpha-numeric and may contain a dash only in between if printf "%s" "$HOST_NAME" | grep -Eoq "^[a-zA-Z0-9-]{1,63}$" \ && [ "${HOST_NAME:0:1}" != "-" ] \ && [ "${HOST_NAME: -1}" != "-" ]; then break else dialog --title "ERROR: Invalid Hostname Format" \ --msgbox "You entered an invalid hostname.\n\nA valid hostname may \ contain only the numbers 0-9, upper and lowercase letters (A-Z and a-z), and \ the minus sign. It must be at most 63 characters long, and may not begin \ or end with a minus sign." 9 75 fi done } # Prompt the user to create a password for the superuser account set_root_passwd(){ inputs_match=false while ! $inputs_match; do input=$(dialog --title "Set the Root Password" --clear --stdout --nocancel \ --insecure --passwordbox "Please enter a password for 'root', the \ system administrative account.\n\nRoot password:" 10 75) confirm_input=$(dialog --title "Set the Root Password" --clear --stdout \ --insecure --passwordbox "Re-enter password to verify:" 8 55) if [ -z "$input" ]; then dialog --title "ERROR: Empty Password" \ --msgbox "You are not allowed to have an empty password." 5 55 elif [ "$input" != "$confirm_input" ]; then dialog --title "ERROR: Passwords Do No Match" \ --msgbox "The two passwords you entered did not match." 5 55 else root_passwd="$input" inputs_match=true fi done } # Prompt the user to create an unprivileged user account create_user() { while true; do FULL_NAME=$(dialog --title "Create a User Account" --nocancel \ --inputbox "The installer will create a user account for you. This is \ the main user account that you will login to and use for non-administrative \ activities.\n\nPlease enter the real name for this user. This information \ will be used for any program that uses the user's real name such as email. \ Entering your full name here is recommended; however, it may be left \ blank.\n\nFull name for the new user:" 15 80 3>&1 1>&2 2>&3) USER_NAME=$(dialog --title "Create a User Account" \ --cancel-label "Back" --inputbox "Please enter a username for the new \ account.\n\nThe username should start with a lower-case letter, which can be \ followed by any combination of numbers, more lower-case letters, or the dash \ symbol.\n\nUsername for your account:" 13 80 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then # Username must start with lowercase letter. May contain lowercase # alpha-numerics and dashes if printf "%s" "$USER_NAME" | grep -Eoq "^[a-z][a-z0-9-]*$" \ && [ "${#USER_NAME}" -lt 33 ]; then # The reserved_username file contains usernames that should be avoided if grep -Fxq "$USER_NAME" "$DIR"/etc/reserved_usernames; then dialog --title "ERROR: Reserved Username" \ --msgbox "The username you entered ($USER_NAME) is reserved for \ use by the system. Please select a different one." 6 70 else inputs_match=false while ! $inputs_match; do input=$(dialog --title "Set the Password for $USER_NAME" --clear \ --stdout --nocancel --insecure --passwordbox "Please enter a \ password for '$USER_NAME'.\n\nChoose a password for the new user:" 10 70) confirm_input=$(dialog --title "Set the Password for $USER_NAME" \ --clear --stdout --insecure \ --passwordbox "Re-enter password to verify:" 8 55) if [ -z "$input" ]; then dialog --title "ERROR: Empty Password" \ --msgbox "You are not allowed to have an empty password." 5 55 elif [ "$input" != "$confirm_input" ]; then dialog --title "ERROR: Passwords Do No Match" \ --msgbox "The two passwords you entered did not match." 5 55 else user_passwd="$input" inputs_match=true fi done break fi else dialog --title "ERROR: Invalid Username Format" \ --msgbox "You entered an invalid username.\n\nThe username must \ start with a lower-case letter, which can be followed by any combination of \ numbers, more lower-case letters, or the dash symbol, and must be no more \ than 32 characters long." 9 80 fi fi done } # Prepare the user's selected disk for partitioning prepare_disk() { SWAP="-" swap_enabled=false block_devices=() # List all available block devices excluding 'rom' and 'loop' for device in $(lsblk -d -n -p -r -e 7,11 -o NAME); do device_size=$(lsblk -d -n -r -o SIZE "$device") block_devices+=("$device" "$device_size") done check_mountpoints while true; do PARTITION_LAYOUT=$(dialog --title "Partition the Disks" \ --cancel-label "Exit to Menu" \ --menu "The installer will now automatically partition a disk for you. \ If you have no preference or are unsure about which partition layout to \ choose, the 'Basic' layout is the simplest and should be enough for most use \ cases.\n\nPartition layout:" 14 80 3 \ "Basic" "Use entire disk" \ "LVM" "Use entire disk and set up LVM" \ "Encrypted" "Use entire disk and set up encrypted LVM" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then DISK=$(dialog --title "Set the Installation Disk" --cancel-label "Back" \ --menu "Select the disk for Parch Linux to be installed on. Note that \ the disk you select will be erased, but not until you have confirmed the \ changes.\n\nDisk to partition:" 16 55 5 \ "${block_devices[@]}" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then # NVME devices use nvme0n1p1, p2, p3 etc. for partition naming PREFIX="" if [[ "$DISK" == *"nvme"* ]]; then PREFIX="p" fi FILE_SYSTEM=$(dialog --title "Set the Filesystem for $DISK_ROOT" \ --nocancel --menu "Select the type of filesystem to use for the \ specified device. If you are unsure, 'ext4' is the default.\n\nFilesystem \ type:" 15 68 5 \ "ext4" "Ext4 journaling filesystem" \ "ext3" "Ext3 journaling filesystem" \ "ext2" "Standard Linux Ext2 filesystem" \ "btrfs" "Btrfs Copy-on-Write B-tree filesystem" \ "xfs" "SGI's journaling filesystem" 3>&1 1>&2 2>&3) dialog --title "Create a Swap Partition" \ --yesno "Would you like to create an optional swap partition? If \ you are unsure, it is recommended to create one." 6 57 if [ $? -eq 0 ]; then # Get the amount of RAM in the system to use as default swap size mem_total=$(free --giga | awk '/^Mem:/{print $2}') if [ "$mem_total" != "0" ]; then mem_total="${mem_total}G" else mem_total=$(free --mega | awk '/^Mem:/{print $2}') mem_total="${mem_total}M" fi while true; do SWAP=$(dialog --title "Allocate Swap Space" \ --inputbox "Specify how much swap space to allocate. If you are \ unsure, the default is to have swap space equal to the amount of RAM in your \ system.\n\nSwap partition size (use 'M' for MiB or 'G' for GiB):" 11 80 \ "$mem_total" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then disk_size_bytes=$(lsblk -b -d -n -o SIZE "$DISK") disk_size_mibs=$((disk_size_bytes/1024/1024)) disk_size_gibs=$((disk_size_mibs/1024)) swap_size=$(printf "%s" "$SWAP" | tr -c -d '[:digit:]') # Input validation for swap size if printf "%s" "$SWAP" | grep -Eoq "^[0-9]+[MG]$" \ && [ "${swap_size:0:1}" != "0" ]; then if [ "${SWAP: -1}" = "M" ] \ && [ "$swap_size" -lt $((disk_size_mibs - 2048)) ]; then swap_enabled=true break elif [ "${SWAP: -1}" = "G" ] \ && [ "$swap_size" -lt $((disk_size_gibs - 2)) ]; then swap_enabled=true break else dialog --title "ERROR: Not Enough Disk Space" \ --msgbox "The amount you entered exceeds the amount of \ space available on the disk. Note that the installer sets aside an additional \ 2 GiB to have enough space for the base installation." 8 60 fi else dialog --title "ERROR: Invalid Format" \ --msgbox "You entered an invalid format. Make sure to use \ 'M' for 'MiB' or 'G' for 'GiB'." 6 60 fi else break fi done fi dialog --title "Confirm the Partition Layout for $DISK" --defaultno \ --yesno "WARNING: All data on the selected disk will be lost! Make \ sure to review your changes before continuing.\n\nDisk to partition: \ $DISK\nPartition layout: $PARTITION_LAYOUT\nFilesystem type: \ $FILE_SYSTEM\nSwap size: $SWAP\n\nAre you sure you want to write the \ changes to the disk?" 13 60 if [ $? -eq 0 ]; then check_lvm_status dialog --infobox "Formatting $DISK..." 3 50 sgdisk --zap-all "$DISK" &> /dev/null wipefs -a "$DISK" &> /dev/null dialog --infobox "Partitioning $DISK..." 3 50 create_partition_label case "$PARTITION_LAYOUT" in "Basic") create_basic_layout ;; "LVM") create_lvm_layout ;; "Encrypted") create_encrypted_layout ;; esac break else main_menu fi fi else main_menu fi done } # Create a new partition label on the selected disk create_partition_label() { # UEFI systems use GPT partitioning and BIOS/CSM systems use MBR if $UEFI; then parted -s "$DISK" mklabel gpt &> /dev/null else parted -s "$DISK" mklabel msdos &> /dev/null fi if [ $? -ne 0 ]; then dialog --title "ERROR: Unable to Partition $DISK" \ --msgbox "The installer encountered an error while partitioning \ $DISK.\n\nMake sure the disk you selected is not active before running the \ installer. If this error keeps occuring, please reboot your machine and try \ again." 8 80 reset ; exit 1 fi } # Partition the selected disk where everything is installed on one partition create_basic_layout() { if $UEFI; then BOOT_PART="${DISK}${PREFIX}1" ROOT_PART="${DISK}${PREFIX}2" if $swap_enabled; then SWAP_PART="${DISK}${PREFIX}3" sgdisk -n 1:0:+512M -n 2:0:-"$SWAP" -n 3:-"$SWAP":-0 \ -t 1:ef00 -t 2:8300 -t 3:8200 "$DISK" &> /dev/null mkswap "$SWAP_PART" &> /dev/null swapon "$SWAP_PART" else sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8300 "$DISK" &> /dev/null fi mkfs.fat -F32 "$BOOT_PART" &> /dev/null else ROOT_PART="${DISK}${PREFIX}1" if $swap_enabled; then SWAP_PART="${DISK}${PREFIX}2" echo -e "n\np\n1\n\n-${SWAP}\nn\np\n2\n\n\nt\n2\n82\nw" \ | fdisk "$DISK" &> /dev/null mkswap "$SWAP_PART" &> /dev/null swapon "$SWAP_PART" else echo -e "n\np\n1\n\n\nw" | fdisk "$DISK" &> /dev/null fi fi case "$FILE_SYSTEM" in btrfs|xfs) mkfs."$FILE_SYSTEM" -f "$ROOT_PART" &> /dev/null ;; *) mkfs."$FILE_SYSTEM" "$ROOT_PART" &> /dev/null ;; esac mount "$ROOT_PART" /mnt if [ $? -eq 0 ]; then mounted=true fi if $UEFI; then mkdir /mnt/boot mount "$BOOT_PART" /mnt/boot fi } # Partition the selected disk and configure LVM create_lvm_layout() { if $UEFI; then BOOT_PART="${DISK}${PREFIX}1" ROOT_PART="${DISK}${PREFIX}2" sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8e00 "$DISK" &> /dev/null mkfs.fat -F32 "$BOOT_PART" &> /dev/null else ROOT_PART="${DISK}${PREFIX}1" echo -e "n\np\n1\n\n\nt\n8e\nw" | fdisk "$DISK" &> /dev/null fi dialog --infobox "Configuring LVM on $ROOT_PART..." 3 50 pvcreate -y "$ROOT_PART" &> /dev/null vgcreate -y "$LVM_GROUP" "$ROOT_PART" &> /dev/null if $swap_enabled; then lvcreate -y -L "$SWAP" "$LVM_GROUP" -n "$LVM_SWAP" &> /dev/null lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null mkswap "/dev/${LVM_GROUP}/${LVM_SWAP}" &> /dev/null swapon "/dev/${LVM_GROUP}/${LVM_SWAP}" else lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null fi case "$FILE_SYSTEM" in btrfs|xfs) mkfs."$FILE_SYSTEM" -f "/dev/${LVM_GROUP}/${LVM_ROOT}" &> /dev/null ;; *) mkfs."$FILE_SYSTEM" "/dev/${LVM_GROUP}/${LVM_ROOT}" &> /dev/null ;; esac mount "/dev/${LVM_GROUP}/${LVM_ROOT}" /mnt if [ $? -eq 0 ]; then mounted=true fi if $UEFI; then mkdir /mnt/boot mount "$BOOT_PART" /mnt/boot fi } # Partition the selected disk and set up root disk encryption (LVM on LUKS) create_encrypted_layout() { # /boot is left unencrypted BOOT_PART="${DISK}${PREFIX}1" ROOT_PART="${DISK}${PREFIX}2" if $UEFI; then sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8e00 "$DISK" &> /dev/null mkfs.fat -F32 "$BOOT_PART" &> /dev/null else echo -e "n\np\n1\n\n+512M\nn\np\n2\n\n\nt\n2\n8e\nw" | fdisk "$DISK" &> /dev/null mkfs.ext4 "$BOOT_PART" &> /dev/null fi inputs_match=false while ! $inputs_match; do input=$(dialog --title "Encrypt $ROOT_PART" --clear --stdout \ --insecure --passwordbox "Enter a passphrase to encrypt \ $ROOT_PART.\n\nThe overall strength of the encryption process depends \ strongly on this passphrase, therefore you should set a passphrase that is \ not easy to guess.\n\nNote that the passphrase you enter will be required \ each time on boot.\n\nEncryption passphrase:" 15 80) if [ $? -eq 0 ]; then confirm_input=$(dialog --title "Encrypt $ROOT_PART" --clear --stdout \ --insecure --passwordbox "Re-enter passphrase to verify:" 8 55) if [ -z "$input" ]; then dialog --title "ERROR: Empty Passphrase" \ --msgbox "You are not allowed to have an empty passphrase." 5 55 elif [ "$input" != "$confirm_input" ]; then dialog --title "ERROR: Passphrases Do No Match" \ --msgbox "The two passphrases you entered did not match." 5 55 elif [ "${#input}" -lt 8 ]; then dialog --title "WARNING: Weak Passphrase" --defaultno \ --yesno "The passphrase you entered is less than 8 characters which \ is considered insecure.\n\nContinue using a weak passphrase?" 8 60 if [ $? -eq 0 ]; then inputs_match=true fi else inputs_match=true fi else dialog --title "Revert Partition Changes" --defaultno \ --yesno "Are you sure you want to cancel the encryption \ process? If you choose yes, you will be returned to the partition menu." 7 65 if [ $? -eq 0 ]; then prepare_disk fi fi done dialog --infobox "Encrypting $ROOT_PART..." 3 50 printf "%s" "$input" | cryptsetup luksFormat "$ROOT_PART" - &> /dev/null printf "%s" "$input" | cryptsetup open "$ROOT_PART" "$CRYPT_DEVICE_NAME" - dialog --infobox "Configuring LVM on $ROOT_PART..." 3 50 pvcreate -y "/dev/mapper/${CRYPT_DEVICE_NAME}" &> /dev/null vgcreate -y "$LVM_GROUP" "/dev/mapper/${CRYPT_DEVICE_NAME}" &> /dev/null if $swap_enabled; then lvcreate -y -L "$SWAP" "$LVM_GROUP" -n "$LVM_SWAP" &> /dev/null lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null mkswap "/dev/mapper/${LVM_GROUP}-${LVM_SWAP}" &> /dev/null swapon "/dev/mapper/${LVM_GROUP}-${LVM_SWAP}" else lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null fi case "$FILE_SYSTEM" in btrfs|xfs) mkfs."$FILE_SYSTEM" -f "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" &> /dev/null ;; *) mkfs."$FILE_SYSTEM" "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" &> /dev/null ;; esac mount "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" /mnt if [ $? -eq 0 ]; then mounted=true fi mkdir /mnt/boot mount "$BOOT_PART" /mnt/boot } # Use the reflector script to update the pacman mirror list update_mirrorlist() { dialog --title "Update the Mirror List" \ --yesno "Would you like to update the Parch Linux mirror list?\n\nUpdating \ the mirror list will speed up the download of packages. If you select no, \ your download speed may be affected." 8 70 if [ $? -eq 0 ]; then dialog --infobox "Updating pacman mirror list..." 3 50 # Sort the 50 most recently synchronized HTTPS mirrors by download speed reflector --latest 50 --protocol https --sort rate --save /etc/pacman.d/mirrorlist fi } # Prompt the user to install the base packages for the system configure_install() { bluetooth_enabled=false dm_enabled=false multilib=false DESKTOP_PACKAGES=() if $UEFI; then DESKTOP_PACKAGES+=('efibootmgr') fi if [ "$PARTITION_LAYOUT" = "LVM" ]; then DESKTOP_PACKAGES+=('lvm2') elif [ "$PARTITION_LAYOUT" = "Encrypted" ]; then DESKTOP_PACKAGES+=('lvm2' 'cryptsetup') fi if [ "$FILE_SYSTEM" = "btrfs" ]; then DESKTOP_PACKAGES+=('btrfs-progs') elif [ "$FILE_SYSTEM" = "xfs" ]; then DESKTOP_PACKAGES+=('xfsprogs') fi if [ "$architecture" = "x86_64" ]; then dialog --title "Enable multilib" \ --yesno "Would you like to enable the 'multilib' repository?\n\nBy \ default, Arch only includes 64-bit software in its repositories. The \ 'multilib' repository contains 32-bit software that is compatible on a 64-bit \ system (e.g. wine, steam, etc)." 9 70 if [ $? -eq 0 ]; then multilib=true fi fi while true; do DESKTOP=$(dialog --title "Choose your Graphical Environment" --no-cancel \ --menu "Select the style of graphical environment you wish to \ use.\n\nGraphical environment:" 12 75 3 \ "Desktop Environment" "Traditional complete graphical user interface" \ "Window Manager" "Standalone minimal graphical user interface" \ "None" "Command-line only interface" 3>&1 1>&2 2>&3) if [ "$DESKTOP" = "Desktop Environment" ]; then GUI=$(dialog --title "Select a Desktop Environment" \ --cancel-label "Back" \ --menu "Select a desktop environment to install:" 15 65 8 \ "Budgie" "Modern GNOME based desktop" \ "Cinnamon" "Traditional desktop experience" \ "GNOME" "Modern simplicity focused desktop" \ "KDE Plasma" "Full featured QT based desktop" \ "LXDE" "Lightweight and efficient desktop" \ "LXQT" "Lightweight and efficient QT based desktop" \ "MATE" "Continuation of the GNOME 2 desktop" \ "Xfce" "Lightweight and modular desktop" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then break fi elif [ "$DESKTOP" = "Window Manager" ]; then GUI=$(dialog --title "Select a Window Manager" \ --cancel-label "Back" \ --menu "Select a window manager to install:" 13 75 6 \ "awesome" "Highly configurable, dynamic window manager" \ "bspwm" "Tiling window manager based on binary space partitioning" \ "Fluxbox" "Stacking window manager based on Blackbox" \ "i3" "Dynamic tiling window manager inspired by wmii" \ "Openbox" "Highly configurable, stacking window manager" \ "xmonad" "Dynamic tiling window manager configured in Haskell" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then break fi else break fi done if [ "$DESKTOP" != "None" ]; then DESKTOP_PACKAGES+=("${DESKTOP_DEFAULTS[@]}") case "$GUI" in "Budgie") DESKTOP_PACKAGES+=('budgie-desktop' 'gnome-control-center') dialog --title "Install Extras" --yesno "Would you like to \ install the 'gnome' group?\n\nIt contains additional utilities and \ applications that integrate well with the Budgie desktop." 8 60 if [ $? -eq 0 ]; then DESKTOP_PACKAGES+=('gnome') fi xinit_config="export XDG_CURRENT_DESKTOP=Budgie:GNOME ; exec budgie-desktop" ;; "Cinnamon") DESKTOP_PACKAGES+=('cinnamon' 'cinnamon-translations' 'nemo-fileroller') xinit_config="exec cinnamon-session" ;; "GNOME") DESKTOP_PACKAGES+=('gnome') dialog --title "Install Extras" --yesno "Would you like to \ install the 'gnome-extra' group?\n\nIt contains additional utilities and \ applications that integrate well with the GNOME desktop." 8 60 if [ $? -eq 0 ]; then DESKTOP_PACKAGES+=('gnome-extra') fi xinit_config="exec gnome-session" ;; "KDE Plasma") DESKTOP_PACKAGES+=('plasma') dialog --title "Install Extras" --yesno "Would you like \ to install the 'kde-applications' group?\n\nIt contains additional utilities \ and applications that integrate well with the Plasma desktop." 8 60 if [ $? -eq 0 ]; then DESKTOP_PACKAGES+=('kde-applications') fi xinit_config="exec startkde" ;; "LXDE") DESKTOP_PACKAGES+=('lxde') xinit_config="exec startlxde" ;; "LXQT") DESKTOP_PACKAGES+=('lxqt' 'breeze-icons') xinit_config="exec startlxqt" ;; "MATE") DESKTOP_PACKAGES+=('mate' 'gtk-engines' 'gtk-engine-murrine') dialog --title "Install Extras" --yesno "Would you like to \ install the 'mate-extra' group?\n\nIt contains additional utilities and \ applications that integrate well with the MATE desktop." 8 60 if [ $? -eq 0 ]; then DESKTOP_PACKAGES+=('mate-extra') fi xinit_config="exec mate-session" ;; "Xfce") DESKTOP_PACKAGES+=('xfce4') dialog --title "Install Extras" --yesno "Would you like to \ install the 'xfce4-goodies' group?\n\nIt contains additional utilities and \ applications that integrate well with the Xfce desktop." 8 60 if [ $? -eq 0 ]; then DESKTOP_PACKAGES+=('xfce4-goodies') fi xinit_config="exec startxfce4" ;; "awesome") DESKTOP_PACKAGES+=('awesome') xinit_config="exec awesome" ;; "bspwm") DESKTOP_PACKAGES+=('bspwm' 'sxhkd') xinit_config="sxhkd & ; exec bspwm" ;; "Fluxbox") DESKTOP_PACKAGES+=('fluxbox') xinit_config="exec startfluxbox" ;; "i3") DESKTOP_PACKAGES+=('i3') xinit_config="exec i3" ;; "Openbox") DESKTOP_PACKAGES+=('openbox') xinit_config="exec openbox-session" ;; "xmonad") DESKTOP_PACKAGES+=('xmonad' 'xmonad-contrib') xinit_config="exec xmonad" ;; esac # GNOME already has networkmanager applet built-in. Plasma uses plasma-nm if [ "$GUI" != "GNOME" ]; then if [ "$GUI" = "KDE Plasma" ]; then DESKTOP_PACKAGES+=('plasma-nm') else DESKTOP_PACKAGES+=('network-manager-applet' 'gnome-keyring') fi fi # Check for available bluetooth devices if $bluetooth; then dialog --title "Enable Bluetooth" \ --yesno "The installer has detected Bluetooth support on your \ system.\n\nWould you like to install and enable the Bluetooth service?" 7 65 if [ $? -eq 0 ]; then bluetooth_enabled=true DESKTOP_PACKAGES+=('bluez' 'bluez-utils' 'pulseaudio-bluetooth') dialog --title "Install Bluetooth Manager" \ --yesno "Would you like to install a graphical Bluetooth \ manager?\n\nThe utility that best integrates with the desktop environment \ you selected will be installed." 8 60 if [ $? -eq 0 ]; then case "$GUI" in "Budgie"|"GNOME") DESKTOP_PACKAGES+=('gnome-bluetooth') ;; "Cinnamon") DESKTOP_PACKAGES+=('blueberry') ;; "KDE Plasma") DESKTOP_PACKAGES+=('bluedevil') ;; *) DESKTOP_PACKAGES+=('blueman') ;; esac fi fi fi dialog --title "Install a Display Manager" \ --yesno "Would you like to install a graphical login manager?\n\nIf you \ select no, 'xinit' will be installed so you can manually start Xorg with the\ 'startx' command." 8 60 if [ $? -eq 0 ]; then DM=$(dialog --title "Install a Display Manager" \ --menu "Select a display manager to install:" 10 50 3 \ "gdm" "GNOME Display Manager" \ "lightdm" "Lightweight Display Manager" \ "sddm" "Simple Desktop Display Manager" 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then dm_enabled=true case "$DM" in "gdm") DESKTOP_PACKAGES+=('gdm') ;; "lightdm") DESKTOP_PACKAGES+=('lightdm' 'lightdm-gtk-greeter' 'lightdm-gtk-greeter-settings') ;; "sddm") DESKTOP_PACKAGES+=('sddm') ;; esac else DESKTOP_PACKAGES+=('xorg-xinit') dialog --title "xinit" \ --msgbox "No display manager selected. Installing 'xorg-xinit'. The \ installer will create a xinitrc file for you.\n\nYou will need to use the \ 'startx' command to start the graphical environment once you login." 9 57 fi else DESKTOP_PACKAGES+=('xorg-xinit') dialog --title "xinit" \ --msgbox "No display manager selected. Installing 'xorg-xinit'. The \ installer will create a xinitrc file for you.\n\nYou will need to use the \ 'startx' command to start the graphical environment once you login." 9 57 fi # Intel/AMD/NVIDIA drivers are not installed on virtual machines if [ "$hypervisor" = "none" ]; then if lspci | grep "VGA" | grep -iq "Intel"; then DESKTOP_PACKAGES+=('xf86-video-intel') fi if lspci | grep "VGA" | grep -iq "NVIDIA"; then gpu_driver=$(dialog --title "Install Graphics Driver" --no-cancel \ --menu "The installer has detected an NVIDIA graphics card on your \ system.\n\nYou may choose to install either the open-source or proprietary \ driver. If you are unsure, the proprietary driver usually offers the best \ performance.\n\nGraphics driver:" 16 70 3 \ "NVIDIA" "Proprietary NVIDIA driver" \ "Nouveau" "Open-source Nouveau driver" \ "None" "-" 3>&1 1>&2 2>&3) if [ "$gpu_driver" = "NVIDIA" ]; then # Get only the GPU PCI device ID gpu_pci_id=$(lspci -nn | grep -ioP 'VGA.*NVIDIA.*\[\K[\w:]+' | sed 's/.*://') # Automatically install the correct driver based on the PCI ID data if grep -Fq "$gpu_pci_id" "$DIR"/etc/nvidia_390_pci_ids; then DESKTOP_PACKAGES+=('nvidia-390xx' 'nvidia-390xx-utils' 'nvidia-390xx-settings') elif grep -Fq "$gpu_pci_id" "$DIR"/etc/nvidia_340_pci_ids; then # Support for nvidia-340xx has been dropped, use nouveau dialog --title "Install Graphics Driver" \ --msgbox "Proprietary driver support has ended for your graphics \ card.\n\nThe open-source Nouveau driver will be installed." 7 65 DESKTOP_PACKAGES+=('xf86-video-nouveau' 'mesa') else DESKTOP_PACKAGES+=('nvidia' 'nvidia-utils' 'nvidia-settings') fi else DESKTOP_PACKAGES+=('xf86-video-nouveau' 'mesa') fi elif lspci | grep "VGA" | grep -q "ATI\|AMD"; then gpu_driver=$(dialog --title "Install Graphics Driver" --no-cancel \ --menu "The installer has detected an ATI/AMD graphics card on your \ system.\nThe appropriate driver to install depends on how modern your GPU \ is.\n\nIf you are unsure, the ATI driver is generally more stable and \ supports the majority of ATI/AMD GPUs. If you have one of the latest AMD GPUs \ (Volcanic Islands or newer), then you should install the AMDGPU \ driver.\n\nGraphics driver:" 17 75 3 \ "ATI" "Open-source ATI/AMD Radeon driver" \ "AMDGPU" "Open-source driver for the latest AMD GPUs" \ "None" "-" 3>&1 1>&2 2>&3) if [ "$gpu_driver" = "ATI" ]; then DESKTOP_PACKAGES+=('xf86-video-ati' 'mesa') else DESKTOP_PACKAGES+=('xf86-video-amdgpu' 'mesa') fi fi else dialog --title "Virtual Machine Detected" \ --msgbox "The installer has detected a virtualized environment: \ $hypervisor\n\nAny required drivers or utilities will be \ installed for you." 7 70 case "$hypervisor" in "vmware") DESKTOP_PACKAGES+=('open-vm-tools' 'xf86-video-vmware' 'xf86-input-vmmouse' 'mesa' 'gtkmm' 'gtkmm3') ;; "oracle") DESKTOP_PACKAGES+=('virtualbox-guest-utils' 'virtualbox-guest-dkms') ;; "parallels") DESKTOP_PACKAGES+=('xf86-video-vesa') ;; *) DESKTOP_PACKAGES+=('xf86-video-fbdev') ;; esac fi fi } install_base() { while true; do dialog --title "Installation Summary" \ --yesno "The base system is ready to be installed on $DISK.\nThe \ following packages will be installed:\n\n${BASE_PACKAGES[*]} \ ${BASE_ESSENTIALS[*]} ${DESKTOP_PACKAGES[*]}\n\nInstall Parch Linux?" 0 0 if [ $? -eq 0 ]; then clear pacstrap /mnt "${BASE_PACKAGES[@]}" "${BASE_ESSENTIALS[@]}" "${DESKTOP_PACKAGES[@]}" if [ $? -eq 0 ]; then installed=true else dialog --title "ERROR: Install Failed" \ --msgbox "Parch Linux failed to install on $DISK.\n\nThe installer \ encountered an error while executing pacstrap." 7 65 reset ; exit 1 fi break else dialog --title "Cancel Installation" \ --yesno "Are you sure you want to exit to the main menu?" 5 55 if [ $? -eq 0 ]; then main_menu fi fi done } # Apply the user's system settings configure_system() { dialog --infobox "Generating the fstab file..." 3 50 # Generate the fstab file genfstab -U -p /mnt >> /mnt/etc/fstab dialog --infobox "Adjusting time zone and system clock..." 3 50 # Set the time zone and adjust the hardware clock to the system time (UTC) ln -sf /usr/share/zoneinfo/"$ZONE" /mnt/etc/localtime if $utc_enabled; then arch-chroot /mnt hwclock --systohc --utc else arch-chroot /mnt hwclock --systohc --localtime fi dialog --infobox "Generating locales..." 3 50 # Set locale and keyboard layout if applicable and generate the locales sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /mnt/etc/locale.gen if [ "$LOCALE" != "en_US.UTF-8" ]; then sed -i "s/#$LOCALE/$LOCALE/" /mnt/etc/locale.gen fi echo "LANG=$LOCALE" > /mnt/etc/locale.conf if [ "$KEYMAP" != "us" ]; then echo "KEYMAP=$KEYMAP" > /mnt/etc/vconsole.conf if [ "$DESKTOP" != "None" ]; then echo -e "Section \"InputClass\"\nIdentifier \"system-keyboard\"\nMatchIsKeyboard \"on\"\nOption \"XkbLayout\" \"$KEYMAP\"\nEndSection" > /mnt/etc/X11/xorg.conf.d/00-keyboard.conf fi fi arch-chroot /mnt locale-gen &> /dev/null dialog --infobox "Configuring system hostname..." 3 50 # Set the hostname and add a matching entry to /etc/hosts echo "$HOST_NAME" > /mnt/etc/hostname echo -e "127.0.0.1\tlocalhost\n::1\t\tlocalhost\n127.0.1.1\t$HOST_NAME.localdomain\t$HOST_NAME" >> /mnt/etc/hosts # Modify mkinitcpio.conf hooks if required and generate a new initramfs if [ "$PARTITION_LAYOUT" != "Basic" ]; then dialog --infobox "Recreating the initramfs image..." 3 50 if [ "$PARTITION_LAYOUT" = "LVM" ]; then sed -i "s/HOOKS=.*/HOOKS=(base udev autodetect modconf block lvm2 filesystems fsck)/" /mnt/etc/mkinitcpio.conf elif [ "$PARTITION_LAYOUT" = "Encrypted" ]; then sed -i "s/HOOKS=.*/HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck)/" /mnt/etc/mkinitcpio.conf fi arch-chroot /mnt mkinitcpio -p linux &> /dev/null fi dialog --infobox "Installing GRUB to $DISK..." 3 50 # Append the required kernel parameters to unlock an encrypted partition if [ "$PARTITION_LAYOUT" = "Encrypted" ]; then root_part_uuid=$(blkid -s UUID -o value "$ROOT_PART") sed -i "s/GRUB_CMDLINE_LINUX=\"\(.*\)\"/GRUB_CMDLINE_LINUX=\"\1 cryptdevice=UUID=$root_part_uuid:$CRYPT_DEVICE_NAME root=\/dev\/mapper\/$LVM_GROUP-$LVM_ROOT\"/" /mnt/etc/default/grub fi # Remove the 'quiet' parameter to have a verbose output during boot sed -i 's/\(GRUB_CMDLINE_LINUX_DEFAULT=\).*/\1\"\"/g' /mnt/etc/default/grub sed -i s/GRUB_DISTRIBUTOR=\"Arch\"/GRUB_DISTRIBUTOR=\"Parch\"/g etc/default/grub # Install GRUB to the target disk and generate the main configuration file if $UEFI; then arch-chroot /mnt grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB &> /dev/null else arch-chroot /mnt grub-install --target=i386-pc "$DISK" &> /dev/null fi dialog --infobox "Generating the GRUB configuration file..." 3 50 arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg &> /dev/null dialog --infobox "Configuring user accounts..." 3 50 # Set the root password and create a user account arch-chroot /mnt chpasswd <<<"root:$root_passwd" # User is added to the 'wheel' group and is granted root privileges with sudo if [ -z "$FULL_NAME" ]; then arch-chroot /mnt useradd -m -g users -G wheel -s /bin/bash "$USER_NAME" else arch-chroot /mnt useradd -m -g users -G wheel -c "$FULL_NAME" -s /bin/bash "$USER_NAME" fi arch-chroot /mnt chpasswd <<<"$USER_NAME:$user_passwd" sed -i '/^# %wheel ALL=(ALL:ALL) ALL/s/^# //' /mnt/etc/sudoers # Uncomment multilib in pacman.conf and refresh the database if $multilib; then sed -i "/\[multilib\]/,/Include/"'s/^#//' /mnt/etc/pacman.conf dialog --infobox "Refreshing pacman database..." 3 50 arch-chroot /mnt pacman -Sy &> /dev/null fi dialog --infobox "Enabling NetworkManager service..." 3 50 arch-chroot /mnt systemctl enable NetworkManager.service &> /dev/null if $bluetooth_enabled; then dialog --infobox "Enabling Bluetooth service..." 3 50 arch-chroot /mnt systemctl enable bluetooth.service &> /dev/null fi # xinitrc is created in user's home directory if display manager is not set if [ "$DESKTOP" != "None" ] && ! $dm_enabled; then dialog --infobox "Generating the xinitrc file..." 3 50 echo "$xinit_config" > /mnt/home/"$USER_NAME"/.xinitrc elif $dm_enabled; then dialog --infobox "Enabling display manager service..." 3 50 arch-chroot /mnt systemctl enable "$DM".service &> /dev/null fi if [ "$hypervisor" != "none" ]; then if [ "$hypervisor" = "oracle" ]; then dialog --infobox "Enabling VirtualBox modules..." 3 50 arch-chroot /mnt systemctl enable vboxservice.service &> /dev/null elif [ "$hypervisor" = "vmware" ]; then dialog --infobox "Enabling VMware Open-VM-Tools..." 3 50 arch-chroot /mnt systemctl enable vmtoolsd.service &> /dev/null arch-chroot /mnt systemctl enable vmware-vmblock-fuse.service &> /dev/null fi fi } # System power menu reboot_system() { if $installed; then while true; do choice=$(dialog --title "Reboot System" --nocancel \ --menu "Parch Linux has finished installing.\nYou must restart your \ system to boot Arch.\n\nPlease select one of the following options:" 13 60 3 \ "Reboot" "Reboot system" \ "Poweroff" "Poweroff system" \ "Exit" "Unmount system and exit to CLI" 3>&1 1>&2 2>&3) dialog --infobox "Unmounting partitions on /mnt..." 3 50 umount -R /mnt case "$choice" in "Reboot") reset ; reboot ; exit ;; "Poweroff") reset ; poweroff ; exit ;; "Exit") reset ; exit ;; esac done else dialog --title "Reboot System" \ --yesno "The installation is incomplete.\n\nAre you sure you want to \ reboot your system?" 7 60 if [ $? -eq 0 ]; then check_mountpoints reset ; reboot ; exit fi fi } # Menu which allows the user to navigate the installer main_menu() { while true; do choice=$(dialog --title "Main Menu" --nocancel \ --menu "Select an option below using the UP/DOWN keys and SPACE or \ ENTER.\nAlternate keys may also be used: '+', '-', and TAB." 19 70 11 \ "KEYMAP" "Set the keyboard layout" \ "LOCALE" "Set the system locale" \ "TIMEZONE" "Set the system time zone" \ "HOSTNAME" "Set the system's hostname" \ "ROOT PASSWORD" "Set the root password" \ "CREATE USER" "Create your user account" \ "PARTITION" "Partition the installation drive" \ "UPDATE MIRRORS" "Update the pacman mirror list" \ "INSTALL" "Install Parch Linux" \ "REBOOT" "Reboot system" \ "EXIT" "Exit Parch Linux Installer" 3>&1 1>&2 2>&3) case "$choice" in "KEYMAP") set_keymap ;; "LOCALE") set_locale ;; "TIMEZONE") set_timezone ;; "HOSTNAME") set_hostname ;; "ROOT PASSWORD") set_root_passwd ;; "CREATE USER") create_user ;; "PARTITION") if $mounted; then dialog --title "Partition the Disks" \ --yesno "A disk is mounted on the system and ready for \ installation.\n\nAre you sure you want to return to partitioning?" 7 70 if [ $? -eq 0 ]; then mounted=false prepare_disk fi else prepare_disk fi ;; "UPDATE MIRRORS") update_mirrorlist ;; "INSTALL") if $mounted; then configure_install install_base configure_system reboot_system else dialog --title "ERROR: No Filesytem Mounted" \ --yesno "The installer was unable to detect a \ mounted filesystem.\n\nReturn to partitioning?" 7 60 if [ $? -eq 0 ]; then prepare_disk fi fi ;; "REBOOT") reboot_system ;; "EXIT") reset ; exit ;; esac done } main() { init check_connection set_keymap set_locale set_timezone set_hostname set_root_passwd create_user prepare_disk update_mirrorlist configure_install install_base configure_system reboot_system } main