#!/usr/bin/bash # vim:ft=sh:fdm=marker:fmr={,} # This program is free software, provided under the GNU GPL # Written by Nathaniel Maia for use in Archlabs # Some ideas and code were taken from other installers # AIF, Cnichi, Calamares, The Arch Wiki.. Credit where credit is due # set -n # immutable variables { readonly DIST="ArchLabs" # Linux distributor readonly VER="1.6.88" # Installer version readonly LIVE="liveuser" # Live session user readonly MNT="/mnt/install" # Install mountpoint readonly ERR="/tmp/errlog" # Built-in error log readonly EFI="/sys/firmware/efi/efivars" readonly TRN="/usr/share/archlabs/installer/lang" readonly RUN="/run/archiso/bootmnt/arch/boot" readonly VM="$(dmesg | grep -i "hypervisor")" readonly SALT="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)" readonly SYS_MEM=$(grep 'MemTotal' /proc/meminfo | awk '{print int($2 / 1024)"M"}') readonly LOCALES="$(awk '/\.UTF-8/ {gsub(/# .*|#/, ""); if($1) print $1 " -"}' /etc/locale.gen)" readonly CONSOLE_MAPS="$(find /usr/share/kbd/keymaps -name '*.map.gz' | awk '{gsub(/\.map\.gz|.*\//, ""); print $1 " -"}')" readonly IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')" if [[ $IGNORE_DEV ]]; then readonly SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')" else readonly SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ {print "/dev/" $1 " " $2}')" fi readonly DEV_COUNT="$(wc -l <<< "$SYS_DEVS")" if grep -q 'GenuineIntel' /proc/cpuinfo; then readonly UCODE="intel-ucode.img" elif grep -q 'AuthenticAMD' /proc/cpuinfo; then readonly UCODE="amd-ucode.img" fi # create associative array for SUBZONES[zone] declare -gA SUBZONES for zone in America Australia Asia Atlantic Africa Europe Indian Pacific Arctic Antarctica; do SUBZONES[$zone]="$(awk "/$zone\// {gsub(/$zone\//, \"\"); print \$3 \" \"\$1}" /usr/share/zoneinfo/zone.tab)" done readonly SUBZONES # make it read only if [[ $DISPLAY && $TERM != 'linux' ]]; then for t in termite st xterm; do hash $t >/dev/null 2>&1 && { readonly TERM_CMD="$t"; break; } done fi # static string of keymap codes and respective language readonly KEYMAPS="us English cm English gb English au English gh English za English ng English ca French cd French gn French tg French fr French de German at German ch German es Spanish latam Spanish br Portuguese pt Portuguese ma Arabic sy Arabic ara Arabic ua Ukrainian cz Czech ru Russian sk Slovak nl Dutch it Italian hu Hungarian cn Chinese tw Taiwanese vn Vietnamese kr Korean jp Japanese th Thai la Lao pl Polish se Swedish is Icelandic fi Finnish dk Danish be Belgian in Indian al Albanian am Armenian bd Bangla ba Bosnian bg Bulgarian dz Berber mm Burmese hr Croatian gr Greek il Hebrew ir Persian iq Iraqi af Afghani fo Faroese ge Georgian ee Estonian kg Kyrgyz kz Kazakh lt Lithuanian mt Maltese mn Mongolian no Norwegian ro Romanian rs Serbian si Slovenian tj Tajik lk Sinhala tr Turkish uz Uzbek ie Irish pk Urdu mv Dhivehi epo Esperanto np Nepali et Amharic sn Wolof ml Bambara tz Swahili ke Swahili bw Tswana ph Filipino id Indonesian my Malay tm Turkmen bt Dzongkha lv Latvian md Moldavian mao Maori by Belarusian me Montenegrin mk Macedonian kh Khmer az Azerbaijani" declare -Agr BMNTS=( [UEFI-grub]="/boot/efi" [UEFI-systemd-boot]="/boot" [BIOS-grub]="/boot" [BIOS-syslinux]="/boot" [UEFI-syslinux]="/boot" ) declare -Agr BOOTLDRS=([BIOS]="grub ${BMNTS[BIOS-grub]} syslinux ${BMNTS[BIOS-syslinux]}" [UEFI]="grub ${BMNTS[UEFI-grub]} systemd-boot ${BMNTS[UEFI-systemd-boot]} syslinux ${BMNTS[UEFI-syslinux]}" ) declare -Agr FS_CMDS=( [ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q" [f2fs]="mkfs.f2fs" [jfs]="mkfs.jfs -q" [xfs]="mkfs.xfs -f" [nilfs2]="mkfs.nilfs2 -q" [ntfs]="mkfs.ntfs -q" [reiserfs]="mkfs.reiserfs -q" [vfat]="mkfs.vfat -F32" ) declare -Agr FS_OPTS=([vfat]="" [ntfs]="" [ext2]="" [ext3]="" [ext4]="discard - off dealloc - off nofail - off noacl - off relatime - off noatime - off nobarrier - off nodelalloc - off" [jfs]="discard - off errors=continue - off errors=panic - off nointegrity - off" [reiserfs]="acl - off nolog - off notail - off replayonly - off user_xattr - off" [xfs]="discard - off filestreams - off ikeep - off largeio - off noalign - off nobarrier - off norecovery - off noquota - off wsync - off" [nilfs2]="discard - off nobarrier - off errors=continue - off errors=panic - off order=relaxed - off order=strict - off norecovery - off" [f2fs]="data_flush - off disable_roll_forward - off disable_ext_identify - off discard - off fastboot - off flush_merge - off inline_xattr - off inline_data - off inline_dentry - off no_heap - off noacl - off nobarrier - off noextent_cache - off noinline_data - off norecovery - off" ) # } init_variables() { declare -g BT="$DIST Installer - (x86_64) - Version $VER" declare -g ROOT_PART="" declare -g BOOT_DEVICE="" declare -g BOOT_PART="" declare -g BOOTLDR="" declare -g EXTRA_MNT="" declare -g EXTRA_MNTS="" declare -g SWAP="none" declare -g SWAP_SIZE="$SYS_MEM" declare -g NEWUSER="" declare -g USER_PASS="" declare -g ROOT_PASS="" declare -g LOGIN_WM="" declare -g LOGIN_TYPE="" declare -g INSTALL_WMS="" declare -g KERNEL="linux" declare -g WM_PACKAGES="" declare -g EXTRA_PACKAGES="" declare -g MKINIT_HOOKS="shutdown" declare -g WARN=false declare -g IS_64BIT=false declare -g AUTOLOGIN=false declare -g CONFIG_DONE=false declare -g SEPERATE_BOOT=false declare -gA BCMDS=( [syslinux]="syslinux-install_update -iam" [grub]="grub-install --recheck --force" [systemd-boot]="bootctl --path=/boot install" ) declare -gA FILES=( [2]="/etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard /etc/vconsole.conf" [3]="/etc/locale.conf /etc/default/locale" [4]="/etc/hostname /etc/hosts" [5]="/etc/sudoers" [6]="/etc/mkinitcpio.conf" [7]="/etc/fstab" [8]="/etc/crypttab" [9]="/etc/default/grub" [10]="/etc/pacman.conf" ) } source_file() { . "$1" || { printf "\nFailed to source library file %s" "$1"; die 1; } } user_creation() { tput cnorm local values values="$(dialog --stdout --no-cancel --separator '~' --ok-label "Submit" --backtitle "$BT" \ --title " $_UserTitle " --insecure --mixedform "$_UserBody" 27 75 10 \ "$_Username" 1 1 "" 1 $((${#_Username} + 2)) 71 0 0 \ "$_Password" 2 1 "" 2 $((${#_Password} + 2)) 71 0 1 \ "$_Password2" 3 1 "" 3 $((${#_Password2} + 2)) 71 0 1 \ "$_RootBody" 6 1 "" 6 $((${#_RootBody} + 1)) 71 0 2 \ "$_Password" 8 1 "" 8 $((${#_Password} + 2)) 71 0 1 \ "$_Password2" 9 1 "" 9 $((${#_Password2} + 2)) 71 0 1 | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)" [[ $? != 0 || $values == "" ]] && return 1 # username doesn't need to be re-encrypted local user user="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" | awk -F'~' '{print $1}')" # all of this is a bit hacky, but we don't ever want the passwords to be stored in plain text # so it decrypts the string '$values', gets the field we want, and re-encrypts it local pass pass2 pass="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" | awk -F'~' '{print $2}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)" pass2="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" | awk -F'~' '{print $3}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)" local rpass rpass2 rpass="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" | awk -F'~' '{print $5}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)" rpass2="$(openssl enc -pbkdf2 -a -d -salt -pass pass:$SALT <<< "$values" | awk -F'~' '{print $6}' | openssl enc -pbkdf2 -a -salt -pass pass:$SALT)" # due to the encryption the string while encrypted will not be empty local empty empty="$(openssl enc -pbkdf2 -a -salt -pass pass:$SALT <<< "")" # both root passwords are empty, so use the user passwords instead [[ $rpass == "" && $rpass2 == "" ]] && { rpass="$pass"; rpass2="$pass2"; } # make sure a username was entered and that the passwords match if [[ ${#user} -eq 0 || $user =~ \ |\' || $user =~ [^a-z0-9\ ] || $pass == "$empty" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]]; then if [[ $pass == "" || "$pass" != "$pass2" || "$rpass" != "$rpass2" ]]; then # password was left empty or doesn't match if [[ $pass == "$empty" ]]; then msgbox "$_ErrTitle" "\nUser password CANNOT be left empty.\n$_TryAgain" elif [[ "$rpass" != "$rpass2" ]]; then msgbox "$_ErrTitle" "$_RootPassErr\n$_TryAgain" else msgbox "$_ErrTitle" "$_UserPassErr\n$_TryAgain" fi else # bad username msgbox "$_UserErrTitle" "$_UserErrBody" user="" fi # recursively loop back unless the user cancels user_creation || return 1 else NEWUSER="$user" USER_PASS="$pass" ROOT_PASS="$rpass" fi return 0 } select_language() { tput civis local lang lang=$(dialog --cr-wrap --stdout --backtitle "$BT" --title " Select Language " --menu \ "\nLanguage - sprache - taal - språk - lingua - idioma - nyelv - língua\n" 0 0 0 \ "1" "English (en_**)" "2" "Español (es_ES)" \ "3" "Português [Brasil] (pt_BR)" "4" "Português (pt_PT)" \ "5" "Français (fr_FR)" "6" "Russkiy (ru_RU)" \ "7" "Italiano (it_IT)" "8" "Nederlands (nl_NL)" \ "9" "Magyar (hu_HU)" "10" "Chinese (zh_CN)") source_file $TRN/english.trans FONT="ter-i16n" case $lang in 1) LOC="en_US.UTF-8" ;; 2) source_file $TRN/spanish.trans && LOC="es_ES.UTF-8" ;; 3) source_file $TRN/p_brasil.trans && LOC="pt_BR.UTF-8" ;; 4) source_file $TRN/portuguese.trans && LOC="pt_PT.UTF-8" ;; 5) source_file $TRN/french.trans && LOC="fr_FR.UTF-8" ;; 6) source_file $TRN/russian.trans && LOC="ru_RU.UTF-8" FONT="LatKaCyrHeb-16" ;; 7) source_file $TRN/italian.trans && LOC="it_IT.UTF-8" ;; 8) source_file $TRN/dutch.trans && LOC="nl_NL.UTF-8" ;; 9) source_file $TRN/hungarian.trans && LOC="hu_HU.UTF-8" FONT="lat2-16" ;; 10) source_file $TRN/chinese.trans && LOC="zh_CN.UTF-8" ;; *) die 0 esac sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen if [[ $LOC != "en_US.UTF-8" ]]; then sed -i "s/#${LOC}/${LOC}/" /etc/locale.gen locale-gen >/dev/null 2>&1 fi [[ $TERM == 'linux' ]] && setfont $FONT >/dev/null 2>&1 export LANG="$LOC" return 0 } setup_keymap() { tput civis KEYMAP="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_PrepLayout " --menu "$_XMapBody" 20 70 12 $KEYMAPS)" [[ $? != 0 || $KEYMAP == "" ]] && return 1 # when a matching console map is not available open a selection dialog if ! [[ $CONSOLE_MAPS =~ "$KEYMAP -" ]]; then CONSOLE_MAP="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_CMapTitle " --menu "$_CMapBody" 20 70 12 $CONSOLE_MAPS)" [[ $? != 0 || $CONSOLE_MAP == "" ]] && return 1 else CONSOLE_MAP="$KEYMAP" fi if [[ $DISPLAY && $TERM != 'linux' ]]; then (type setxkbmap >/dev/null 2>&1) && setxkbmap $KEYMAP >/dev/null 2>&1 else (type loadkeys >/dev/null 2>&1) && loadkeys $CONSOLE_MAP >/dev/null 2>&1 fi return 0 } setup_timezone() { tput civis ZONE="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_TimeZTitle " --menu "$_TimeZBody" 20 70 10 America - Australia - \ Asia - Atlantic - Africa - Europe - Indian - Pacific - Arctic - Antarctica -)" [[ $? != 0 || $ZONE == "" ]] && return 1 SUBZONE="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_TimeZTitle " --menu "$_TimeSubZBody" 20 70 12 ${SUBZONES[$ZONE]})" [[ $? != 0 || $SUBZONE == "" ]] && return 1 yesno "$_TimeZTitle" "$_TimeZQ $ZONE/$SUBZONE?\n" && return 0 || setup_timezone } window_manager() { INSTALL_WMS="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_WMChoice " --checklist "$_WMChoiceBody\n" 0 0 0 \ "openbox" "A lightweight, powerful, and highly configurable stacking window manager" off \ "bspwm" "A tiling window manager that represents windows as the leaves of a binary tree" off \ "i3-gaps" "A fork of i3 window manager with more features including gaps" off \ "dwm" "A customized fork of dwm, with patches and modifications" off \ "gnome" "A desktop environment that aims to be simple and easy to use" off \ "cinnamon" "A desktop environment combining a traditional desktop layout with modern graphical effects" off \ "xfce4" "A lightweight and modular desktop environment based on GTK+ 2 and 3" off)" [[ $? != 0 || $INSTALL_WMS == "" ]] && return 1 WM_NUM=$(awk '{print NF}' <<< "$INSTALL_WMS") # packages needed for the selected window manager for wm in $INSTALL_WMS; do LOGIN_CHOICES="${LOGIN_CHOICES}$wm - " case $wm in cinnamon) WM_PACKAGES+=" $wm" ;; bspwm) WM_PACKAGES+=" $wm sxhkd" ;; gnome) WM_PACKAGES+=" $wm gnome-extra" ;; i3-gaps) WM_PACKAGES+=" $wm i3status perl-anyevent-i3" ;; xfce4) WM_PACKAGES+=" $wm xfce4-goodies xfce4-pulseaudio-plugin" ;; openbox) WM_PACKAGES+=" $wm obconf archlabs-obkey archlabs-kickshaw archlabs-skippy-xd tint2 conky jgmenu" ;; esac done if [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps) ]]; then WM_PACKAGES+=" archlabs-polybar jsoncpp libmpdclient archlabs-screenlock archlabs-oblogout" WM_PACKAGES+=" archlabs-paranoid lxappearance rofi termite thunar" elif [[ $INSTALL_WMS =~ (xfce4) ]]; then WM_PACKAGES+=" archlabs-oblogout archlabs-screenlock archlabs-paranoid" fi # choose which to login if [[ $WM_NUM -eq 1 ]]; then LOGIN_WM="$INSTALL_WMS" else LOGIN_WM="$(dialog --cr-wrap --stdout --no-cancel --backtitle "$BT" \ --title " $_WMLogin " --menu "$_WMLoginBody" 0 0 0 $LOGIN_CHOICES)" [[ $LOGIN_WM == "" ]] && LOGIN_WM="$(awk '{print $1}' <<< "$INSTALL_WMS")" fi # chose login type if yesno "$_WMLogin" "$_LoginTypeBody\n" "xinit" "lightdm"; then LOGIN_TYPE='xinit' FILES[11]="/home/$NEWUSER/.xinitrc" else LOGIN_TYPE='lightdm' WM_PACKAGES+=" lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice" FILES[11]="/etc/lightdm/lightdm.conf $MNT/etc/lightdm/lightdm-gtk-greeter.conf" fi EXTRA_PACKAGES="$WM_PACKAGES" # autologin yesno "$_WMLogin" "$_AutoLoginBody\n" && AUTOLOGIN=true || AUTOLOGIN=false case $LOGIN_WM in i3-gaps) LOGIN_WM='i3' ;; xfce4) LOGIN_WM='startxfce4' ;; gnome) LOGIN_WM='gnome-session' ;; openbox) LOGIN_WM='openbox-session' ;; cinnamon) LOGIN_WM='cinnamon-session' ;; esac return 0 } extra_packages() { local pkgs pkgs="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_ExtraPackages " --checklist "$_ExtraPackagesBody\n" 0 0 30 \ "firefox" "A popular open-source graphical web browser from Mozilla" off \ "chromium" "an open-source graphical web browser based on the Blink rendering engine" off \ "opera" "Fast and secure, free of charge web browser from Opera Software" off \ "epiphany" "A GNOME web browser based on the WebKit rendering engine" off \ "qutebrowser" "A keyboard-focused vim-like web browser based on Python and PyQt5" off \ "atom" "An open-source text editor developed by GitHub that is licensed under the MIT License" off \ "geany" "A fast and lightweight IDE" off \ "emacs" "An extensible, customizable, self-documenting real-time display editor" off \ "neovim" "A fork of Vim aiming to improve user experience, plugins, and GUIs." off \ "mousepad" "A simple text editor" off \ "rxvt-unicode" "A unicode enabled rxvt-clone terminal emulator" off \ "termite" "A minimal VTE-based terminal emulator" off \ "tilix" "A tiling terminal emulator for Linux using GTK+ 3" off \ "terminator" "Terminal emulator that supports tabs and grids" off \ "tilda" "A Gtk based drop down terminal for Linux and Unix" off \ "xfce4-terminal" "A terminal emulator based in the Xfce Desktop Environment" off \ "thunar" "A modern file manager for the Xfce Desktop Environment" off \ "pcmanfm" "A fast and lightweight file manager based in Lxde" off \ "gnome-disk-utility" "Disk Management Utility" off \ "gnome-system-monitor" "View current processes and monitor system state" off \ "steam" "A popular game distribution platform by Valve" off \ "vlc" "A free and open source cross-platform multimedia player" off \ "mpd" "A flexible, powerful, server-side application for playing music" off \ "ncmpcpp" "An mpd client and almost exact clone of ncmpc with some new features" off \ "cmus" "A small, fast and powerful console music player for Unix-like operating systems" off \ "audacious" "A free and advanced audio player based on GTK+" off \ "nicotine+" "A graphical client for Soulseek" off \ "lollypop" "A new music playing application" off \ "rhythmbox" "Music playback and management application" off \ "deadbeef" "A GTK+ audio player for GNU/Linux" off \ "clementine" "A modern music player and library organizer" off \ "thunderbird" "Standalone mail and news reader from mozilla" off \ "geary" "A lightweight email client for the GNOME desktop" off \ "evolution" "Manage your email, contacts and schedule" off \ "mutt" "Small but very powerful text-based mail client" off \ "deluge" "A BitTorrent client written in python" off \ "transmission-gtk" "Free BitTorrent client GTK+ GUI" off \ "qbittorrent" "An advanced BitTorrent client" off \ "hexchat" "A popular and easy to use graphical IRC client" off \ "pidgin" "Multi-protocol instant messaging client" off \ "weechat" "Fast, light and extensible IRC client" off \ "irssi" "Modular text mode IRC client" off \ "libreoffice-fresh" "Full featured office suite" off \ "abiword" "Fully-featured word processor" off \ "calligra" "A set of applications for productivity" off \ "evince" "A document viewer" off \ "zathura" "Minimalistic document viewer" off \ "qpdfview" "A tabbed PDF viewer" off \ "mupdf" "Lightweight PDF and XPS viewer" off \ "gpicview" "Lightweight image viewer" off \ "gimp" "GNU Image Manipulation Program" off \ "inkscape" "Professional vector graphics editor" off \ "krita" "Edit and paint images" off \ "simplescreenrecorder" "A feature-rich screen recorder" off \ "obs-studio" "Free opensource streaming/recording software" off \ "openshot" "An open-source, non-linear video editor for Linux based on MLT framework" off \ "kdenlive" "A non-linear video editor for Linux using the MLT video framework" off \ "audacity" "A program that lets you manipulate digital audio waveforms" off \ "guvcview" "Capture video from camera devices" off \ "gpick" "Advanced color picker using GTK+ toolkit" off \ "gcolor2" "A simple GTK+2 color selector" off \ "plank" "An elegant, simple, and clean dock" off \ "docky" "Full fledged dock that makes opening applications and managing windows faster and easier" off \ "cairo-dock" "Light eye-candy fully themable animated dock" off \ "qt5ct" "GUI for managing Qt based application themes, icons, and fonts" off \ "ttf-hack" "A hand groomed and optically balanced typeface based on Bitstream Vera Mono" off \ "ttf-anonymous-pro" "A family of four fixed-width fonts designed especially with coding in mind" off \ "ttf-font-awesome" "Iconic font designed for Bootstrap" off \ "ttf-fira-code" "Monospaced font with programming ligatures" off \ "noto-fonts" "Google Noto fonts" off \ "noto-fonts-cjk" "Google Noto CJK fonts (Chinese, Japanese, Korean)" off)" [[ $pkgs =~ vlc ]] && pkgs+=" qt4" [[ $pkgs =~ mpd ]] && pkgs+=" mpc" [[ $pkgs =~ mupdf ]] && pkgs+=" mupdf-tools" [[ $pkgs =~ qt5ct ]] && pkgs+=" qt5-styleplugins" [[ $pkgs =~ steam ]] && pkgs+=" steam-native-runtime" [[ $pkgs =~ zathura ]] && pkgs+=" zathura-pdf-poppler" [[ $pkgs =~ noto-fonts ]] && pkgs+=" noto-fonts-emoji" [[ $pkgs =~ cairo-dock ]] && pkgs+=" cairo-dock-plug-ins" [[ $pkgs =~ kdenlive ]] && pkgs+=" kdebase-runtime dvdauthor frei0r-plugins breeze breeze-gtk" if [[ $INSTALL_WMS =~ dwm ]] && ! [[ $pkgs =~ ttf-hack ]]; then pkgs+=" ttf-hack" fi if [[ $pkgs =~ (qutebrowser|qbittorrent|kdenlive|vlc) ]] && ! [[ $pkgs =~ qt5ct ]]; then pkgs+=" qt5ct qt5-styleplugins" fi EXTRA_PACKAGES="$EXTRA_PACKAGES$([[ $pkgs ]] && printf " %s" "$pkgs")" return 0 } mirrorlist_cmd() { local key="5f29642060ab983b31fdf4c2935d8c56" local ip="$(curl -s "http://api.ipstack.com/check&fields=ip&?access_key=${key}" | val_from_json 'ip')" if hash reflector >/dev/null 2>&1; then MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate" yesno "$_MirrorTitle" "$_MirrorSetup" "Automatic" "Custom" && return 0 local c="$(curl -s "http://api.ipstack.com/${ip}?access_key=${key}&fields=country_name" | val_from_json 'country_name')" if [[ $c != "" ]]; then MIRROR_CMD="reflector --country $c --score 80 --latest 40 --fastest 10 --sort rate" fi tput cnorm MIRROR_CMD="$(dialog --cr-wrap --no-cancel --stdout --backtitle "$BT" \ --title " $_MirrorTitle " --inputbox "$_MirrorCmd\n --score n Limit the list to the n servers with the highest score. --latest n Limit the list to the n most recently synchronized servers. --fastest n Return the n fastest mirrors that meet the other criteria. --sort {age,rate,country,score,delay} 'age': Last server synchronization; 'rate': Download rate; 'country': Server location; 'score': MirrorStatus score; 'delay': MirrorStatus delay.\n" 0 0 "$MIRROR_CMD")" else local c="$(curl -s "http://api.ipstack.com/${ip}?access_key=${key}&fields=country_code" | val_from_json 'country_code')" local w="https://www.archlinux.org/mirrorlist" if [[ $c != "" ]]; then if [[ $c =~ (CA|US) ]]; then MIRROR_CMD="curl -s '$w/?country=US&country=CA&protocol=https&use_mirror_status=on'" else MIRROR_CMD="curl -s '$w/?country=${c}&protocol=https&use_mirror_status=on'" fi else MIRROR_CMD="curl -s '$w/?country=US&country=CA&country=NZ&country=GB&country=AU&protocol=https&use_mirror_status=on'" fi fi return 0 } display_selection() { msgbox "$_PrepTitle" "\nConfiguration values used for install\n\n Root: $ROOT_PART Boot: $BOOT_PART Swap: $SWAP Extra: ${EXTRA_MNTS:-None} LVM: $LVM LUKS: $LUKS Bootloader: $BOOTLDR Boot Mount: ${BMNTS[$SYS-$BOOTLDR]} Boot Command: ${BCMDS[$BOOTLDR]} New User: $NEWUSER Login: $LOGIN_WM Autologin: $AUTOLOGIN Login Type: $LOGIN_TYPE Hostname: $HOSTNAME Locale: $LOCALE Keymap: $KEYMAP Timezone: $ZONE/$SUBZONE Kernel: $KERNEL Sessions: $INSTALL_WMS Mirrors: $MIRROR_CMD Packages: $EXTRA_PACKAGES\n" } configure_install() { tput cnorm HOSTNAME="$(getinput "$_ConfHost" "$_HostNameBody" "${DIST,,}")" [[ $? != 0 || $HOSTNAME == "" ]] && return 1 tput civis LOCALE="$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_ConfLocale " --menu "$_LocaleBody" 25 70 20 $LOCALES)" [[ $? != 0 || $LOCALE == "" ]] && return 1 setup_timezone || return 1 mirrorlist_cmd || return 1 user_creation || return 1 window_manager || return 1 yesno 'Choose Kernel' "\nUse the current kernel or the LTS kernel?\n" 'Current' 'LTS' && KERNEL='linux' || KERNEL='linux-lts' extra_packages || return 1 CONFIG_DONE=true return 0 } edit_configs() { if [[ $CURRENT_MENU != "edit" ]]; then SELECTED=1 CURRENT_MENU="edit" elif (( SELECTED < 10 )); then (( SELECTED++ )) fi tput civis SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_EditTitle " --default-item $SELECTED --menu "$_EditBody" 0 0 0 \ "1" "Exit & Reboot" "2" "Keyboard" "3" "Locale" "4" "Hostname" "5" "Sudoers" \ "6" "Mkinitcpio.conf" "7" "Fstab" "8" "Crypttab" "9" "${BOOTLDR^}" "10" "Pacman.conf" \ "11" "$LOGIN_TYPE") if [[ ! $SELECTED || $SELECTED -eq 1 ]]; then wrap_up "$_InstFinBody" 'Reboot' 'Back' 'reboot' else local existing_files="" for f in $(echo "${FILES[$SELECTED]}"); do [[ -e ${MNT}$f ]] && existing_files+=" ${MNT}$f" done [[ ! $existing_files ]] && msgbox "$_ErrTitle" "$_NoFileErr" || vim -O $existing_files fi edit_configs } main() { if [[ $CURRENT_MENU != "main" ]]; then SELECTED=1 CURRENT_MENU="main" elif (( SELECTED < 8 )); then ((SELECTED++)) # increment the highlighted menu item fi tput civis SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \ --title " $_PrepTitle " --default-item $SELECTED --menu "$_PrepBody" 0 0 0 \ "1" "$_PrepShowDev" "2" "$_PrepParts" "3" "$_PrepLUKS" "4" "$_PrepLVM" \ "5" "$_PrepMount" "6" "$_PrepConfig" "7" "Check Choices" "8" "$_PrepInstall" \ "9" "$_Done") # if trying to install the system, make sure the partitions are mounted # and that the needed config variables and user variables have been set up if [[ $SELECTED ]]; then if [[ $SELECTED -eq 8 ]]; then check_install_ready || return 1 elif [[ ($SELECTED -eq 2 || $SELECTED -eq 5) && $WARN != true ]]; then msgbox "$_PrepTitle" "$_WarnMount" WARN=true fi fi case $SELECTED in 1) show_devices ;; 2) edit_partitions ;; 3) luks_menu || SELECTED=1 ;; 4) lvm_menu || SELECTED=1 ;; 5) mount_main || SELECTED=1 ;; 6) configure_install ;; 7) display_selection ;; 8) install_main && edit_configs ;; *) wrap_up "$_CloseInstBody" 'Exit' 'Back' 'exit' esac } # must be done first init_variables for file in /usr/share/archlabs/installer/lib/?*.sh; do source_file "$file" done # trap Ctrl-C to properly exit trap sigint INT for arg in $@; do case $arg in --debug|-d) debug ;; esac done select_language setup_keymap check_requirements identify_system msgbox "$_WelTitle $DIST Installer" "$_WelBody" while true; do main done