Split main dialogs to their own lib file, add checklist function, split package choices to menu style

This commit is contained in:
natemaia 2018-11-11 22:25:06 -08:00
parent fdd77684a0
commit 3c76cf943a
11 changed files with 781 additions and 657 deletions

View File

@ -70,14 +70,16 @@ _MirrorCmd="\nThe command below will be used to sort the mirrorlist, a short des
# window managers and packages
_WMChoice="Select WMs or DEs"
_WMChoiceBody="\nUse [Space] to (de)select window manager(s) or desktop environment(s) to install.\n\nDepending on your choice additional packages may be installed to improve the experience."
_ExtraPackages="Extra Packages"
_ExtraPackagesBody="\nUse [Space] to (de)select packages(s) to install from the list below.\n\nNOTE: Some packages may already be installed by your DE (if any) or added automatically depending on your choice of WM."
_Packages="Install Packages"
_PackageMenu="\nSelect a package category to choose packages from that category.\n\nWhen finished select '$_Done' to finalize choices and continue.\n\nAdditional packages can be added by simply re-visiting the menu, however removing choices will require starting from the beginning of the configure menu."
_PackageBody="\nUse [Space] to (de)select packages(s) to install from the list below.\n\nNOTE: Some packages may already be installed by your DE (if any) or added automatically depending on your choice of WM. Additionally, extra packages may be installed to improve the experience for another choice eg. when installing qutebrowser qt5ct (the Qt5 theme tool) will also be installed."
# login setup
_WMLogin="Select Login Type"
_LoginTypeBody="\nSelect how you want to log in to the computer, using a display manager or xinit."
_WMLoginBody="\nSelect which window manager or desktop to use as your primary login."
_AutoLoginBody="\nDo you want the new user to be automatically logged in when the computer starts?"
_WMLogin="Select Login Managment"
_LoginTypeBody="\nSelect how you want to log in, using a display manager or xinit."
_WMLoginBody="\nSelect which window manager or desktop to use as your primary login.\n\nThis can be changed by editing your ~/.xinitrc"
_AutoLoginBody="\nDo you want to enable auto-login and have 'startx' run when the computer starts?"
# Set keymap, hwclock, local and timezone
_CMapTitle="Virtual Console Keymap"

View File

@ -1,582 +1,19 @@
#!/usr/bin/bash
# vim:fdm=marker:fmr={,}
# shellcheck disable=2154,2034,2153
# This program is free software, provided under the GNU GPL
# Written by Nathaniel Maia for use in Archlabs
# Some ideas and code has been taken from other installers
# AIF, Cnichi, Calamares, The Arch Wiki.. Credit where credit is due
# set -n
# shellcheck disable=2154,2034,2153
# globals {
# immutable values
readonly VER="1.7.17" # Installer version
# immutable globals
readonly VER="1.7.18" # Installer version
readonly DIST="ArchLabs" # Linux distributor
readonly MNT="/mnt/install" # Install mountpoint
readonly ERR="/tmp/errlog" # Built-in error log
readonly DBG="/tmp/debuglog" # Built-in error log
# mutable values
declare -g WARN=false
declare -g AUTOLOGIN=false
declare -g CONFIG_DONE=false
declare -g SEPERATE_BOOT=false
declare -g HAS_NETWORK=false
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_PART=""
declare -g SWAP_SIZE=""
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=""
declare -g WM_PACKAGES=""
declare -g PACKAGES=""
declare -g MYSHELL=""
declare -g MKINIT_HOOKS="shutdown"
# }
select_language() {
tput civis
local lang
local title="\nLanguage - sprache - taal - språk - lingua - idioma - nyelv - língua\n"
lang=$(menubox "Select Language" "$title" 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)")
local srcdir="/usr/share/archlabs/installer/lang"
src $srcdir/english.trans
FONT="ter-i16n"
case $lang in
1) LOC="en_US.UTF-8" ;;
2) src $srcdir/spanish.trans && LOC="es_ES.UTF-8" ;;
3) src $srcdir/p_brasil.trans && LOC="pt_BR.UTF-8" ;;
4) src $srcdir/portuguese.trans && LOC="pt_PT.UTF-8" ;;
5) src $srcdir/french.trans && LOC="fr_FR.UTF-8" ;;
6) src $srcdir/russian.trans && LOC="ru_RU.UTF-8" FONT="LatKaCyrHeb-16" ;;
7) src $srcdir/italian.trans && LOC="it_IT.UTF-8" ;;
8) src $srcdir/dutch.trans && LOC="nl_NL.UTF-8" ;;
9) src $srcdir/hungarian.trans && LOC="hu_HU.UTF-8" FONT="lat2-16" ;;
10) src $srcdir/chinese.trans && LOC="zh_CN.UTF-8" ;;
*) die
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
}
user_creation() {
tput cnorm
local values
if ! 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)"; then
return 1
fi
# 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 encrypting the string, when empty, once encrypted it wont 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 == "$empty" && $rpass2 == "$empty" ]] && { 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 == "$empty" || "$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 || return 1
else
export NEWUSER="$user"
export USER_PASS="$pass"
export ROOT_PASS="$rpass"
fi
return 0
}
select_keymap() {
tput civis
if ! KEYMAP="$(menubox "$_PrepLayout" "$_XMapBody" 20 70 12 \
'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' 'ro' 'Romanian' \
'no' 'Norwegian' 'rs' 'Serbian' 'si' 'Slovenian' 'tj' 'Tajik' 'lk' 'Sinhala' \
'tr' 'Turkish' 'uz' 'Uzbek' 'ie' 'Irish' 'pk' 'Urdu' 'mv' 'Dhivehi' \
'np' 'Nepali' 'et' 'Amharic' 'sn' 'Wolof' 'ml' 'Bambara' 'tz' 'Swahili' \
'ke' 'Swahili' 'bw' 'Tswana' 'ph' 'Filipino' 'my' 'Malay' 'tm' 'Turkmen' \
'id' 'Indonesian' 'bt' 'Dzongkha' 'lv' 'Latvian' 'md' 'Moldavian' 'mao' 'Maori' \
'by' 'Belarusian' 'az' 'Azerbaijani' 'mk' 'Macedonian' 'kh' 'Khmer' 'epo' 'Esperanto' \
'me' 'Montenegrin')"; then
return 1
fi
# when a matching console map is not available open a selection dialog
if [[ $CMAPS == *"$KEYMAP"* ]]; then
CMAP="$KEYMAP"
else
if ! CMAP="$(menubox "$_CMapTitle" "$_CMapBody" 20 70 12 $CMAPS)"; then
return 1
fi
fi
if [[ $DISPLAY && $TERM != 'linux' ]]; then
setxkbmap $KEYMAP >/dev/null 2>&1
else
loadkeys $CMAP >/dev/null 2>&1
fi
return 0
}
select_timezone() {
# create associative array for SUBZONES[zone]
local f="/usr/share/zoneinfo/zone.tab"
declare -A SUBZONES
for i in America Australia Asia Atlantic Africa Europe Indian Pacific Arctic Antarctica; do
SUBZONES[$i]="$(awk '/'"$i"'\// {gsub(/'"$i"'\//, ""); print $3, $1}' $f)"
done
tput civis
if ! ZONE="$(menubox "$_TimeZTitle" "$_TimeZBody" 20 70 10 \
'America' '-' 'Australia' '-' 'Asia' '-' 'Atlantic' '-' 'Africa' '-' \
'Europe' '-' 'Indian' '-' 'Pacific' '-' 'Arctic' '-' 'Antarctica' '-')"; then
return 1
fi
if ! SUBZONE="$(menubox "$_TimeZTitle" "$_TimeSubZBody" 20 70 12 ${SUBZONES[$ZONE]})"; then
return 1
fi
yesno "$_TimeZTitle" "$_TimeZQ $ZONE/$SUBZONE?\n" && return 0 || select_timezone
}
select_wm_or_de() {
tput civis
if ! 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)"; then
return 1
fi
[[ $INSTALL_WMS ]] || INSTALL_WMS='openbox'
WM_NUM=$(awk '{print NF}' <<< "$INSTALL_WMS")
WM_PACKAGES="${INSTALL_WMS/dwm/}" # remove dwm as we are compiling from source
WM_PACKAGES="${WM_PACKAGES// / }" # remove double spaces from the string
# packages needed for the selected WMs/DEs
for wm in $INSTALL_WMS; do
LOGIN_CHOICES="${LOGIN_CHOICES}$wm - "
case $wm in
cinnamon) : ;; # none
bspwm) WM_PACKAGES+=" sxhkd" ;;
gnome) WM_PACKAGES+=" gnome-extra" ;;
i3-gaps) WM_PACKAGES+=" i3status perl-anyevent-i3" ;;
xfce4) WM_PACKAGES+=" xfce4-goodies xfce4-pulseaudio-plugin" ;;
openbox) WM_PACKAGES+=" archlabs-obkey obconf archlabs-kickshaw tint2 archlabs-skippy-xd conky jgmenu" ;;
esac
done
if [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps) ]]; then
WM_PACKAGES+=" libmpdclient rofi jsoncpp archlabs-screenlock termite archlabs-oblogout thunar archlabs-polybar archlabs-paranoid"
elif [[ $INSTALL_WMS =~ (xfce4) ]]; then
WM_PACKAGES+=" archlabs-oblogout archlabs-screenlock archlabs-paranoid"
fi
# choose how to log in
select_login_method || return 1
# choose which WM/DE to start at login
if [[ $LOGIN_TYPE == 'xinit' ]]; then
if [[ $WM_NUM -eq 1 ]]; then
LOGIN_WM="$INSTALL_WMS"
else
if ! LOGIN_WM="$(menubox "$_WMLogin" "$_WMLoginBody" 0 0 0 $LOGIN_CHOICES)"; then
return 1
fi
fi
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
# autologin
yesno "$_WMLogin" "$_AutoLoginBody\n" && AUTOLOGIN=true || AUTOLOGIN=false
else
AUTOLOGIN=false
fi
# add packages to the main package list
PACKAGES="$WM_PACKAGES"
return 0
}
select_login_method() {
if ! LOGIN_TYPE="$(menubox "$_WMLogin" "$_LoginTypeBody" 0 0 0 \
"xinit" "Console login without a display manager" \
"lightdm" "Lightweight display manager with a gtk greeter")"; then
return 1
fi
if [[ $LOGIN_TYPE == 'lightdm' ]]; then
WM_PACKAGES+=" lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
EDIT_FILES[11]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
else
EDIT_FILES[11]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
fi
}
select_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"
{ [[ $INSTALL_WMS =~ dwm ]] && ! [[ $pkgs =~ ttf-hack ]]; } && pkgs+=" ttf-hack"
{ [[ $pkgs =~ (qutebrowser|qbittorrent|kdenlive|vlc) ]] && ! [[ $pkgs =~ qt5ct ]]; } && pkgs+=" qt5ct qt5-styleplugins"
PACKAGES+=" $pkgs" # add chosen packages to the main package list
PACKAGES="${PACKAGES/^ /}" # remove leading spaces from the package string
return 0
}
select_mirrorlist_command() {
local ip c
local key="5f29642060ab983b31fdf4c2935d8c56"
if hash reflector >/dev/null 2>&1; then
MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate --verbose"
yesno "$_MirrorTitle" "$_MirrorSetup" "Automatic" "Custom" && return 0
ip="$(json 'ip' "check&?access_key=${key}&fields=ip")"
c="$(json 'country_name' "${ip}?access_key=${key}&fields=country_name")"
MIRROR_CMD="reflector --country $c --score 80 --latest 40 --fastest 10 --sort rate --verbose"
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
ip="$(json 'ip' "check&?access_key=${key}&fields=ip")"
c="$(json 'country_code' "${ip}?access_key=${key}&fields=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_system_settings() {
local cmd mnt pkgs
cmd="${BCMDS[$BOOTLDR]}"
mnt="${BMNTS[$SYS-$BOOTLDR]}"
msgbox "$_PrepTitle" "\n\n---------- PARTITION CONFIGURATION ------------
Root: ${ROOT_PART:-None}
Boot: ${BOOT_PART:-${BOOT_DEVICE:-None}}
Swap: ${SWAP_PART:-None}
Size: ${SWAP_SIZE:-None}
Extra: ${EXTRA_MNTS:-${EXTRA_MNT:-None}}
Hooks: ${MKINIT_HOOKS:-None}
LVM: ${LVM:-None}
LUKS: ${LUKS:-None}
---------- BOOTLOADER CONFIGURATION -----------
Loader: ${BOOTLDR:-None}
Mount: ${mnt:-None}
Command: ${cmd:-None}
------------ SYSTEM CONFIGURATION -------------
Locale: ${LOCALE:-None}
Keymap: ${KEYMAP:-None}
Hostname: ${HOSTNAME:-None}
Timezone: ${ZONE:-None}/${SUBZONE:-None}
------------ LOGIN CONFIGURATION --------------
User: ${NEWUSER:-None}
Shell: ${MYSHELL:-None}
Session: ${LOGIN_WM:-None}
Autologin: ${AUTOLOGIN:-None}
Management: ${LOGIN_TYPE:-None}
------------ PACKAGES AND MIRRORS -------------
Kernel: ${KERNEL:-None}
Sessions: ${INSTALL_WMS:-None}
Mirrors: ${MIRROR_CMD:-None}
Packages: $(printq "${PACKAGES:-None}")\n"
}
configure_system_settings() {
tput cnorm
if ! HOSTNAME="$(getinput "$_ConfHost" "$_HostNameBody" "${DIST,,}")"; then
return 1
fi
tput civis
if ! LOCALE="$(menubox "$_ConfLocale" "$_LocaleBody" 25 70 20 $LOCALES)"; then
return 1
fi
select_timezone || return 1
user_creation || return 1
tput civis
if ! MYSHELL="$(menubox "$_ShellTitle" "$_ShellBody" 0 0 0 '/bin/zsh' '-' '/bin/bash' '-')"; then
return 1
fi
tput civis
if [[ $HAS_NETWORK == true ]]; then
if ! KERNEL="$(menubox "$_KernelTitle" "$_KernelBody" 0 0 0 'linux' '-' 'linux-lts' '-')"; then
return 1
fi
select_wm_or_de || return 1
select_extra_packages || return 1
select_mirrorlist_command || return 1
else
# defaults for when there is no network connection
KERNEL='linux'
AUTOLOGIN=true
LOGIN_TYPE='xinit'
INSTALL_WMS='openbox'
LOGIN_WM='openbox-session'
MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate --verbose"
EDIT_FILES[11]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
fi
export CONFIG_DONE=true
return 0
}
edit_system_configs() {
if [[ $CURRENT_MENU != "edit" ]]; then
SELECTED=1; CURRENT_MENU="edit"
elif (( SELECTED < 11 )); then
(( SELECTED++ ))
fi
tput civis
local exitstr
[[ $DEBUG == true ]] && exitstr="View Log & Reboot" || exitstr="Reboot"
SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_EditTitle " --default-item $SELECTED --menu "$_EditBody" 0 0 0 \
"1" "$exitstr" "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
[[ $DEBUG == true ]] && more $DEBUG
die 127
else
local existing_files=""
for f in $(printf "%s" "${EDIT_FILES[$SELECTED]}"); do
[[ -e ${MNT}$f ]] && existing_files+=" ${MNT}$f"
done
if [[ ! $existing_files ]]; then
msgbox "$_ErrTitle" "$_NoFileErr"
else
if hash vim >/dev/null 2>&1; then
vim -O $existing_files
else
for f in $existing_files; do
if hash nano >/dev/null 2>&1; then
nano $f
else
vi $f
fi
done
fi
fi
fi
edit_system_configs
}
main() {
if [[ $CURRENT_MENU != "main" ]]; then
SELECTED=1
@ -596,12 +33,13 @@ main() {
# and that the needed config variables and user variables have been set up
if [[ $SELECTED ]]; then
if [[ $SELECTED -eq 8 || $SELECTED -eq 6 ]]; then
{ [[ $SELECTED -eq 8 ]] && icheck 1 || icheck; } || return 1
{ [[ $SELECTED -eq 8 ]] && preinstall_check 1 || preinstall_check; } || return 1
elif [[ ($SELECTED -eq 2 || $SELECTED -eq 5) && $WARN != true ]]; then
msgbox "$_PrepTitle" "$_WarnMount" && WARN=true
fi
fi
# setting $SELECTED to $SELECTED - 1 when a step fails retains the highlighted menu item
case $SELECTED in
1) device_tree ;;
2) partition || SELECTED=1 ;;
@ -627,12 +65,14 @@ for arg in "$@"; do case $arg in
--debug|-d) debug ;;
esac done
# initial choices/prep
devices
# initial prep
select_language
select_keymap
checks
sysid
# call checks before identify so we can try mounting efivarfs
system_checks
system_identify
system_devices
# welcome message
msgbox "$_WelTitle $DIST Installer" "$_WelBody"

View File

@ -6,8 +6,6 @@
# this file is not meant to be run directly
# sourcing this file in a non bash shell is not advised
# set -n
declare -gA BCMDS=(
[syslinux]="syslinux-install_update -iam"
[grub]="grub-install --recheck --force"

601
src/lib/dialogs.sh Normal file
View File

@ -0,0 +1,601 @@
#!/usr/bin/bash
# vim:ft=sh:fdm=marker:fmr={,}
# archlabs installer library script file
# this file is not meant to be run directly
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154,2034,2153
# mutable globals {
declare -g WARN=false
declare -g AUTOLOGIN=false
declare -g CONFIG_DONE=false
declare -g SEPERATE_BOOT=false
declare -g HAS_NETWORK=false
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_PART=""
declare -g SWAP_SIZE=""
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=""
declare -g WM_PACKAGES=""
declare -g PACKAGES=""
declare -g MYSHELL=""
declare -g MKINIT_HOOKS="shutdown"
# package extras
# if you add a package to $PACKAGES in any dialog and it uses or requires some
# additional packages, you can add them here to keep it simple for the end user
declare -gA PKG_EXT=(
[vlc]="qt4"
[mpd]="mpc"
[mupdf]="mupdf-tools"
[qt5ct]="qt5-styleplugins"
[steam]="steam-native-runtime"
[zathura]="zathura-pdf-poppler"
[cairo-dock]="cairo-dock-plug-ins"
[noto-fonts]="noto-fonts-emoji"
[kdenlive]="kdebase-runtime dvdauthor frei0r-plugins breeze breeze-gtk"
[vlc]="qt5ct qt5-styleplugins"
[kdenlive]="qt5ct qt5-styleplugins" # duplicates are stripped with `uniq` later
[qbittorrent]="qt5ct qt5-styleplugins"
[qutebrowser]="qt5ct qt5-styleplugins"
)
# }
# basic dialog helper functions
msgbox() {
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $1 " --msgbox "$2\n" 0 0
}
menubox() {
local title="$1"
local body="$2"
local h=$3
local w=$4
local n=$5
shift 5
local response
if ! response="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $title " --menu "$body" $h $w $n "$@")"; then
return 1
fi
printf "%s" "$response"
}
checkbox() {
local title="$1"
local body="$2"
local h=$3
local w=$4
local n=$5
shift 5
local response
if ! response="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $title " --checklist "$body" $h $w $n "$@")"; then
return 1
fi
printf "%s" "$response"
}
getinput() {
local answer
if ! answer="$(dialog --cr-wrap --max-input 63 --stdout --no-cancel --backtitle "$BT" --title " $1 " --inputbox "$2" 0 0 "$3")" || [[ $answer == '' ]]; then
return 1
fi
printf "%s" "$answer"
}
infobox() {
local sec="$3"
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $1 " --infobox "$2\n" 0 0
sleep ${sec:-2}
}
yesno() {
# usage: yesno <title> <text> [<yes_label> <no_label> [<no>]]
# three options: one --default-no and custom labels, one just custom labels, and one basic.
tput civis
if [[ $# -eq 5 && $5 == "no" ]]; then
dialog --cr-wrap --backtitle "$BT" --defaultno --title " $1 " \
--yes-label "$3" --no-label "$4" --yesno "$2\n" 0 0
elif [[ $# -eq 4 ]]; then
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yes-label "$3" \
--no-label "$4" --yesno "$2\n" 0 0
else
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yesno "$2\n" 0 0
fi
}
# larger specific dialog menus
select_language() {
tput civis
local lang
local title="\nLanguage - sprache - taal - språk - lingua - idioma - nyelv - língua\n"
lang=$(menubox "Select Language" "$title" 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)")
local srcdir="/usr/share/archlabs/installer/lang"
src $srcdir/english.trans
FONT="ter-i16n"
case $lang in
1) LOC="en_US.UTF-8" ;;
2) src $srcdir/spanish.trans && LOC="es_ES.UTF-8" ;;
3) src $srcdir/p_brasil.trans && LOC="pt_BR.UTF-8" ;;
4) src $srcdir/portuguese.trans && LOC="pt_PT.UTF-8" ;;
5) src $srcdir/french.trans && LOC="fr_FR.UTF-8" ;;
6) src $srcdir/russian.trans && LOC="ru_RU.UTF-8" FONT="LatKaCyrHeb-16" ;;
7) src $srcdir/italian.trans && LOC="it_IT.UTF-8" ;;
8) src $srcdir/dutch.trans && LOC="nl_NL.UTF-8" ;;
9) src $srcdir/hungarian.trans && LOC="hu_HU.UTF-8" FONT="lat2-16" ;;
10) src $srcdir/chinese.trans && LOC="zh_CN.UTF-8" ;;
*) die
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
}
user_creation() {
tput cnorm
local values
if ! 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)"; then
return 1
fi
# 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 encrypting the string, when empty, once encrypted it wont 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 == "$empty" && $rpass2 == "$empty" ]] && { 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 == "$empty" || "$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 || return 1
else
export NEWUSER="$user"
export USER_PASS="$pass"
export ROOT_PASS="$rpass"
fi
return 0
}
select_keymap() {
tput civis
if ! KEYMAP="$(menubox "$_PrepLayout" "$_XMapBody" 20 70 12 \
'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' 'ro' 'Romanian' \
'no' 'Norwegian' 'rs' 'Serbian' 'si' 'Slovenian' 'tj' 'Tajik' 'lk' 'Sinhala' \
'tr' 'Turkish' 'uz' 'Uzbek' 'ie' 'Irish' 'pk' 'Urdu' 'mv' 'Dhivehi' \
'np' 'Nepali' 'et' 'Amharic' 'sn' 'Wolof' 'ml' 'Bambara' 'tz' 'Swahili' \
'ke' 'Swahili' 'bw' 'Tswana' 'ph' 'Filipino' 'my' 'Malay' 'tm' 'Turkmen' \
'id' 'Indonesian' 'bt' 'Dzongkha' 'lv' 'Latvian' 'md' 'Moldavian' 'mao' 'Maori' \
'by' 'Belarusian' 'az' 'Azerbaijani' 'mk' 'Macedonian' 'kh' 'Khmer' 'epo' 'Esperanto' \
'me' 'Montenegrin')"; then
return 1
fi
# when a matching console map is not available open a selection dialog
if [[ $CMAPS == *"$KEYMAP"* ]]; then
CMAP="$KEYMAP"
else
if ! CMAP="$(menubox "$_CMapTitle" "$_CMapBody" 20 70 12 $CMAPS)"; then
return 1
fi
fi
if [[ $DISPLAY && $TERM != 'linux' ]]; then
setxkbmap $KEYMAP >/dev/null 2>&1
else
loadkeys $CMAP >/dev/null 2>&1
fi
return 0
}
select_timezone() {
# create associative array for SUBZONES[zone]
local f="/usr/share/zoneinfo/zone.tab"
declare -A SUBZONES
for i in America Australia Asia Atlantic Africa Europe Indian Pacific Arctic Antarctica; do
SUBZONES[$i]="$(awk '/'"$i"'\// {gsub(/'"$i"'\//, ""); print $3, $1}' $f)"
done
tput civis
if ! ZONE="$(menubox "$_TimeZTitle" "$_TimeZBody" 20 70 10 \
'America' '-' 'Australia' '-' 'Asia' '-' 'Atlantic' '-' 'Africa' '-' \
'Europe' '-' 'Indian' '-' 'Pacific' '-' 'Arctic' '-' 'Antarctica' '-')"; then
return 1
fi
if ! SUBZONE="$(menubox "$_TimeZTitle" "$_TimeSubZBody" 20 70 12 ${SUBZONES[$ZONE]})"; then
return 1
fi
yesno "$_TimeZTitle" "$_TimeZQ $ZONE/$SUBZONE?\n" && return 0 || select_timezone
}
select_wm_or_de() {
declare -g PACKAGES=""
tput civis
if ! 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)"; then
return 1
fi
[[ $INSTALL_WMS ]] || INSTALL_WMS='openbox'
WM_NUM=$(awk '{print NF}' <<< "$INSTALL_WMS")
WM_PACKAGES="${INSTALL_WMS/dwm/}" # remove dwm as we are compiling from source
WM_PACKAGES="${WM_PACKAGES// / }" # remove double spaces from the string
# packages needed for the selected WMs/DEs
for wm in $INSTALL_WMS; do
LOGIN_CHOICES="${LOGIN_CHOICES}$wm - "
case $wm in
dwm) WM_PACKAGES+=" ttf-hack" ;;
bspwm) WM_PACKAGES+=" sxhkd" ;;
gnome) WM_PACKAGES+=" gnome-extra" ;;
i3-gaps) WM_PACKAGES+=" i3status perl-anyevent-i3" ;;
xfce4) WM_PACKAGES+=" xfce4-goodies xfce4-pulseaudio-plugin" ;;
openbox) WM_PACKAGES+=" archlabs-obkey obconf archlabs-kickshaw tint2 archlabs-skippy-xd conky jgmenu" ;;
esac
done
if [[ $INSTALL_WMS =~ (openbox|bspwm|i3-gaps) ]]; then
WM_PACKAGES+=" libmpdclient jsoncpp archlabs-screenlock termite archlabs-oblogout archlabs-polybar archlabs-paranoid rofi thunar"
elif [[ $INSTALL_WMS =~ xfce4 ]]; then
WM_PACKAGES+=" archlabs-oblogout archlabs-screenlock archlabs-paranoid"
fi
# choose how to log in
select_login_method || return 1
# choose which WM/DE to start at login
if [[ $LOGIN_TYPE == 'xinit' ]]; then
if [[ $WM_NUM -eq 1 ]]; then
LOGIN_WM="$INSTALL_WMS"
else
if ! LOGIN_WM="$(menubox "$_WMLogin" "$_WMLoginBody" 0 0 0 $LOGIN_CHOICES)"; then
return 1
fi
fi
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
# autologin
yesno "$_WMLogin" "$_AutoLoginBody\n" && AUTOLOGIN=true || AUTOLOGIN=false
else
AUTOLOGIN=false
fi
# add packages to the main package list
PACKAGES="$WM_PACKAGES"
return 0
}
select_login_method() {
if ! LOGIN_TYPE="$(menubox "$_WMLogin" "$_LoginTypeBody" 0 0 0 \
"xinit" "Console login without a display manager" \
"lightdm" "Lightweight display manager with a gtk greeter")"; then
return 1
fi
if [[ $LOGIN_TYPE == 'lightdm' ]]; then
WM_PACKAGES+=" lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings accountsservice"
EDIT_FILES[11]="/etc/lightdm/lightdm.conf /etc/lightdm/lightdm-gtk-greeter.conf"
else
EDIT_FILES[11]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
fi
}
select_packages() {
if [[ $CURRENT_MENU != "packages" ]]; then
SELECTED=1
CURRENT_MENU="packages"
elif (( SELECTED < 9 )); then
((SELECTED++)) # increment the highlighted menu item
fi
tput civis
SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_Packages " --default-item $SELECTED --menu "$_PackageMenu" 0 0 0 \
"1" "Web Browsers" "2" "Text Editors" "3" "Terminal Emulators" \
"4" "Music and Video Players" "5" "Mail and Chat" "6" "Office and Editing" \
"7" "Management and Fonts" "8" "Miscellaneous" "9" "$_Done")
if [[ $SELECTED -lt 9 ]]; then
case $SELECTED in
1) PACKAGES+=" $(select_browsers)" ;;
2) PACKAGES+=" $(select_editors)" ;;
3) PACKAGES+=" $(select_terminals)" ;;
4) PACKAGES+=" $(select_music_and_video)" ;;
5) PACKAGES+=" $(select_mail_and_chat)" ;;
6) PACKAGES+=" $(select_office_and_editing)" ;;
7) PACKAGES+=" $(select_managment)" ;;
8) PACKAGES+=" $(select_extra)" ;;
esac
select_packages
else
# add any extra for each package
for pkg in $PACKAGES; do
[[ ${PKG_EXT[$pkg]} ]] && PACKAGES+=" ${PKG_EXT[$pkg]}"
done
# remove duplicates and leading spaces
PACKAGES="$(uniq <<< "${PACKAGES/^ /}")"
return 0
fi
}
select_mirrorcmd() {
local ip c
local key="5f29642060ab983b31fdf4c2935d8c56"
if hash reflector >/dev/null 2>&1; then
MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate --verbose"
yesno "$_MirrorTitle" "$_MirrorSetup" "Automatic" "Custom" && return 0
ip="$(json 'ip' "check&?access_key=${key}&fields=ip")"
c="$(json 'country_name' "${ip}?access_key=${key}&fields=country_name")"
MIRROR_CMD="reflector --country $c --score 80 --latest 40 --fastest 10 --sort rate --verbose"
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
ip="$(json 'ip' "check&?access_key=${key}&fields=ip")"
c="$(json 'country_code' "${ip}?access_key=${key}&fields=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_system_settings() {
local cmd mnt pkgs
cmd="${BCMDS[$BOOTLDR]}"
mnt="${BMNTS[$SYS-$BOOTLDR]}"
msgbox "$_PrepTitle" "
---------- PARTITION CONFIGURATION ------------
Root: ${ROOT_PART:-None}
Boot: ${BOOT_PART:-${BOOT_DEVICE:-None}}
Swap: ${SWAP_PART:-None}
Size: ${SWAP_SIZE:-None}
Extra: ${EXTRA_MNTS:-${EXTRA_MNT:-None}}
Hooks: ${MKINIT_HOOKS:-None}
LVM: ${LVM:-None}
LUKS: ${LUKS:-None}
---------- BOOTLOADER CONFIGURATION -----------
Loader: ${BOOTLDR:-None}
Mount: ${mnt:-None}
Command: ${cmd:-None}
------------ SYSTEM CONFIGURATION -------------
Locale: ${LOCALE:-None}
Keymap: ${KEYMAP:-None}
Hostname: ${HOSTNAME:-None}
Timezone: ${ZONE:-None}/${SUBZONE:-None}
------------ LOGIN CONFIGURATION --------------
User: ${NEWUSER:-None}
Shell: ${MYSHELL:-None}
Session: ${LOGIN_WM:-None}
Autologin: ${AUTOLOGIN:-None}
Management: ${LOGIN_TYPE:-None}
------------ PACKAGES AND MIRRORS -------------
Kernel: ${KERNEL:-None}
Sessions: ${INSTALL_WMS:-None}
Mirrors: ${MIRROR_CMD:-None}
Packages: $(print4 "${PACKAGES:-None}")
"
}
configure_system_settings() {
tput cnorm
if ! HOSTNAME="$(getinput "$_ConfHost" "$_HostNameBody" "${DIST,,}")"; then
return 1
fi
tput civis
if ! LOCALE="$(menubox "$_ConfLocale" "$_LocaleBody" 25 70 20 $LOCALES)"; then
return 1
fi
select_timezone || return 1
user_creation || return 1
tput civis
if ! MYSHELL="$(menubox "$_ShellTitle" "$_ShellBody" 0 0 0 '/bin/zsh' '-' '/bin/bash' '-')"; then
return 1
fi
tput civis
if [[ $HAS_NETWORK == true ]]; then
if ! KERNEL="$(menubox "$_KernelTitle" "$_KernelBody" 0 0 0 'linux' '-' 'linux-lts' '-')"; then
return 1
fi
select_wm_or_de || return 1
select_packages || return 1
select_mirrorcmd || return 1
else
# defaults for when there is no network connection
KERNEL='linux'
AUTOLOGIN=true
LOGIN_TYPE='xinit'
INSTALL_WMS='openbox'
LOGIN_WM='openbox-session'
MIRROR_CMD="reflector --score 100 -l 50 -f 10 --sort rate --verbose"
EDIT_FILES[11]="/home/$NEWUSER/.xinitrc /home/$NEWUSER/.xprofile"
fi
export CONFIG_DONE=true
return 0
}
edit_system_configs() {
if [[ $CURRENT_MENU != "edit" ]]; then
SELECTED=1; CURRENT_MENU="edit"
elif (( SELECTED < 11 )); then
(( SELECTED++ ))
fi
tput civis
local exitstr
[[ $DEBUG == true ]] && exitstr="View debug log before the exit & reboot" || exitstr="Exit & reboot"
SELECTED=$(dialog --cr-wrap --stdout --backtitle "$BT" \
--title " $_EditTitle " --default-item $SELECTED --menu "$_EditBody" 0 0 0 \
"1" "$exitstr" "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
[[ $DEBUG == true ]] && more $DEBUG
# when die() is passed 127 as the exit code it will issue `systemctl -i reboot`
die 127
else
local existing_files=""
for f in $(printf "%s" "${EDIT_FILES[$SELECTED]}"); do
[[ -e ${MNT}$f ]] && existing_files+=" ${MNT}$f"
done
if [[ $existing_files ]]; then
if hash vim >/dev/null 2>&1; then
vim -O $existing_files
else
for f in $existing_files; do
if hash nano >/dev/null 2>&1; then nano $f; else vi $f; fi
done
fi
else
msgbox "$_ErrTitle" "$_NoFileErr"
fi
fi
edit_system_configs
}

View File

@ -6,8 +6,6 @@
# this file is not meant to be run directly
# sourcing this file in a non bash shell is not advised
# set -n
readonly RUN="/run/archiso/bootmnt/arch/boot"
readonly VM="$(dmesg | grep -i "hypervisor")"
@ -232,12 +230,10 @@ mirrorlist_sort() {
printf "\n\n%s\n\n" "Sorting the mirrorlist"
if hash reflector >/dev/null 2>&1; then
$MIRROR_CMD --save $MNT/etc/pacman.d/mirrorlist --verbose ||
reflector --score 100 -l 50 -f 10 \
--sort rate --verbose --save $MNT/etc/pacman.d/mirrorlist
reflector --score 100 -l 50 -f 10 --sort rate --verbose --save $MNT/etc/pacman.d/mirrorlist
else
{ eval $MIRROR_CMD || curl -s 'https://www.archlinux.org/mirrorlist/all/'; } |
sed -e 's/^#Server/Server/' -e '/^#/d' |
rankmirrors -n 10 - > $MNT/etc/pacman.d/mirrorlist
sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 10 - > $MNT/etc/pacman.d/mirrorlist
fi
}
@ -288,3 +284,4 @@ suckless_install() {
printf "\n\n%s\n\n" "To configure dwm edit /home/$NEWUSER/suckless/dwm/config.h and recompile with 'sudo make clean install'"
sleep 2
}

View File

@ -7,7 +7,6 @@
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154
# set -n
declare -g LUKS=""
declare -gx LUKS_DEV=""

View File

@ -7,7 +7,6 @@
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154
# set -n
declare -g LVM=""
declare -g VOL_GROUP_MB=0

View File

@ -7,7 +7,6 @@
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154,2153,2046
# set -n
readonly SYS_MEM="$(awk '/MemTotal/ {print int($2 / 1024)"M"}' /proc/meminfo)"
readonly SALT="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32 | head -n 1)"

129
src/lib/package.sh Normal file
View File

@ -0,0 +1,129 @@
#!/usr/bin/bash
# vim:ft=sh:fdm=marker:fmr={,}
# archlabs installer library script file
# this file is not meant to be run directly
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154,2153,2046
select_browsers() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"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)"
printf "%s" "$pkgs"
}
select_editors() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"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)"
printf "%s" "$pkgs"
}
select_terminals() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"termite" "A minimal VTE-based terminal emulator" off \
"rxvt-unicode" "A unicode enabled rxvt-clone terminal emulator" off \
"terminator" "Terminal emulator that supports tabs and grids" off \
"tilix" "A tiling terminal emulator for Linux using GTK+ 3" 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)"
printf "%s" "$pkgs"
}
select_music_and_video() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"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)"
printf "%s" "$pkgs"
}
select_mail_and_chat() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"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 \
"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)"
printf "%s" "$pkgs"
}
select_office_and_editing() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"libreoffice-fresh" "Full featured office suite" off \
"abiword" "Fully-featured word processor" off \
"calligra" "A set of applications for productivity" off \
"gimp" "GNU Image Manipulation Program" off \
"inkscape" "Professional vector graphics editor" off \
"krita" "Edit and paint images" 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 \
"simplescreenrecorder" "A feature-rich screen recorder" off)"
printf "%s" "$pkgs"
}
select_managment() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"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 \
"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)"
printf "%s" "$pkgs"
}
select_extra() {
local pkgs=""
pkgs="$(checkbox "$_Packages" "$_PackageBody" 0 0 0 \
"steam" "A popular game distribution platform by Valve" off \
"deluge" "A BitTorrent client written in python" off \
"transmission-gtk" "Free BitTorrent client GTK+ GUI" off \
"qbittorrent" "An advanced BitTorrent client" 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 \
"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)"
printf "%s" "$pkgs"
}

View File

@ -7,7 +7,6 @@
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154,2153,2046
# set -n
declare -Agr FS_CMDS=(
[ext2]="mkfs.ext2 -q" [ext3]="mkfs.ext3 -q" [ext4]="mkfs.ext4 -q"

View File

@ -7,21 +7,25 @@
# sourcing this file in a non bash shell is not advised
# shellcheck disable=2154
# set -n
chrun() {
# run a shell command in the chroot dir $MNT
arch-chroot $MNT /bin/bash -c "$1"
}
json() {
# get a value from http://api.ipstack.com in json format using my API key
# this includes: ip, geolocation, country name
curl -s "http://api.ipstack.com/$2" | python3 -c "import sys, json; print(json.load(sys.stdin)['$1'])"
}
src() {
# source a file ($1), if it fails we die with an error message
. "$1" || { printf "\nFailed to source file %s\n" "$1"; die 1; }
}
ssd() {
# returns 0 (true) when the device passed ($1) is NOT a rotational device
local dev=$1
dev=${dev#/dev/}
[[ $dev =~ nvme ]] && dev=${dev%p[0-9]*} || dev=${dev%[0-9]*}
@ -29,13 +33,16 @@ ssd() {
}
die() {
# die peacefully
local exitcode=0
(( $# == 0 )) || exitcode=$1
tput cnorm
if [[ -d $MNT ]] && cd; then
# use `fuser` to kill processes using the mounted directory before umounting it
fuser -km $MNT
umount_dir $MNT
# when passed 127 as the exit code, kill the loop mount to avoid hangups and reboot the system
if [[ $exitcode -eq 127 ]]; then
fuser -km /run/archiso/bootmnt
umount -l /run/archiso/bootmnt
@ -46,51 +53,13 @@ die() {
}
sigint() {
# used to trap SIGINT and cleanly exit the program
printf "\n** CTRL-C caught"
die 1
}
msgbox() {
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $1 " --msgbox "$2\n" 0 0
}
menubox() {
local title="$1"
local body="$2"
local h=$3
local w=$4
local n=$5
shift 5
if ! response="$(dialog --cr-wrap --stdout --backtitle "$BT" --title " $title " --menu "$body" $h $w $n "$@")"; then
return 1
fi
printf "%s\n" "$response"
}
oneshot() {
[[ -e /tmp/.ai_$1 || ! $(type $1) ]] && return 0
$1 || return 1
touch "/tmp/.ai_$1"
return 0
}
getinput() {
local answer
if ! answer="$(dialog --cr-wrap --max-input 63 --stdout --no-cancel --backtitle "$BT" --title " $1 " --inputbox "$2" 0 0 "$3")" || [[ $answer == '' ]]; then
return 1
fi
printf "%s" "$answer"
}
infobox() {
local sec="$3"
tput civis
dialog --cr-wrap --backtitle "$BT" --title " $1 " --infobox "$2\n" 0 0
sleep ${sec:-2}
}
printq() {
print4() {
# takes an arbitrary number of input fields and prints them out in fourths on separate lines
local str="$*"
if [[ ${#str} -gt $(( ${COLUMNS:-$(tput cols)} / 2 )) ]]; then
q=$(awk '{print int(NF / 4)}' <<< "$str")
@ -118,7 +87,14 @@ printq() {
printf "%s\n" "$str"
}
devices() {
oneshot() {
[[ -e /tmp/.ai_$1 || ! $(type $1) ]] && return 0
$1 || return 1
touch "/tmp/.ai_$1"
return 0
}
system_devices() {
IGNORE_DEV="$(lsblk -lno NAME,MOUNTPOINT | awk '/\/run\/archiso\/bootmnt/ {sub(/[1-9]/, ""); print $1}')"
if [[ $IGNORE_DEV ]]; then
SYS_DEVS="$(lsblk -lno NAME,SIZE,TYPE | awk '/disk/ && !'"/$IGNORE_DEV/"' {print "/dev/" $1 " " $2}')"
@ -129,7 +105,7 @@ devices() {
declare -grx SYS_DEVS IGNORE_DEV DEV_COUNT
}
sysid() {
system_identify() {
declare -g IS_64BIT=false
local efidir="/sys/firmware/efi"
@ -157,7 +133,7 @@ sysid() {
return 0
}
checks() {
system_checks() {
[[ $(whoami) == "root" ]] || { infobox "$_ErrTitle" "$_NotRoot\n$_Exit" && die 1; }
grep -qw 'lm' /proc/cpuinfo || { infobox "$_ErrTitle" "$_Not64Bit\n$_Exit" && die 1; }
@ -176,6 +152,14 @@ checks() {
return 0
}
preinstall_checks() {
[[ $(lsblk -o MOUNTPOINT) =~ $MNT ]] || { msgbox "$_ErrTitle" "$_ErrNoMount"; export SELECTED=4; return 1; }
if [[ $# -eq 1 ]]; then
[[ $CONFIG_DONE == true ]] || { msgbox "$_ErrTitle" "$_ErrNoConfig"; export SELECTED=5; return 1; }
fi
return 0
}
echeck() {
# return if the last process exited normally
local last_exit_code=$?
@ -198,29 +182,6 @@ echeck() {
return 0
}
icheck() {
[[ $(lsblk -o MOUNTPOINT) =~ $MNT ]] || { msgbox "$_ErrTitle" "$_ErrNoMount"; export SELECTED=4; return 1; }
if [[ $# -eq 1 ]]; then
[[ $CONFIG_DONE == true ]] || { msgbox "$_ErrTitle" "$_ErrNoConfig"; export SELECTED=5; return 1; }
fi
return 0
}
yesno() {
# usage: yesno <title> <text> [<yes_label> <no_label> [<no>]]
# three options: one --default-no and custom labels, one just custom labels, and one basic.
tput civis
if [[ $# -eq 5 && $5 == "no" ]]; then
dialog --cr-wrap --backtitle "$BT" --defaultno --title " $1 " \
--yes-label "$3" --no-label "$4" --yesno "$2\n" 0 0
elif [[ $# -eq 4 ]]; then
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yes-label "$3" \
--no-label "$4" --yesno "$2\n" 0 0
else
dialog --cr-wrap --backtitle "$BT" --title " $1 " --yesno "$2\n" 0 0
fi
}
debug() {
set -x
exec 3>| $DBG