Convert whiptail to dialog.

Signed-off-by: Dan Schaper <dan.schaper@pi-hole.net>
pull/4781/head
Dan Schaper 2 years ago committed by Dan Schaper
parent 37889f27de
commit bf57a786e6

@ -2,7 +2,7 @@
# shellcheck disable=SC1090 # shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017-2021 Pi-hole, LLC (https://pi-hole.net) # (c) Pi-hole (https://pi-hole.net)
# Network-wide ad blocking via your own hardware. # Network-wide ad blocking via your own hardware.
# #
# Installs and Updates Pi-hole # Installs and Updates Pi-hole
@ -32,6 +32,14 @@ export PATH+=':/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
# Local variables will be in lowercase and will exist only within functions # Local variables will be in lowercase and will exist only within functions
# It's still a work in progress, so you may see some variance in this guideline until it is complete # It's still a work in progress, so you may see some variance in this guideline until it is complete
# Dialog result codes
# dialog code values can be set by environment variables, we only override if
# the env var is not set or empty.
: "${DIALOG_OK:=0}"
: "${DIALOG_CANCEL:=1}"
: "${DIALOG_ESC:=255}"
# List of supported DNS servers # List of supported DNS servers
DNS_SERVERS=$(cat << EOM DNS_SERVERS=$(cat << EOM
Google (ECS, DNSSEC);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860:0:0:0:0:8844 Google (ECS, DNSSEC);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860:0:0:0:0:8844
@ -93,7 +101,7 @@ if [ -z "${USER}" ]; then
USER="$(id -un)" USER="$(id -un)"
fi fi
# whiptail dialog dimensions: 20 rows and 70 chars width assures to fit on small screens and is known to hold all content. # dialog dimensions: 20 rows and 70 chars width assures to fit on small screens and is known to hold all content.
r=20 r=20
c=70 c=70
@ -317,7 +325,7 @@ package_manager_detect() {
# Packages required to perform the os_check (stored as an array) # Packages required to perform the os_check (stored as an array)
OS_CHECK_DEPS=(grep dnsutils) OS_CHECK_DEPS=(grep dnsutils)
# Packages required to run this install script (stored as an array) # Packages required to run this install script (stored as an array)
INSTALLER_DEPS=(git iproute2 whiptail ca-certificates) INSTALLER_DEPS=(git iproute2 dialog ca-certificates)
# Packages required to run Pi-hole (stored as an array) # Packages required to run Pi-hole (stored as an array)
PIHOLE_DEPS=(cron curl iputils-ping psmisc sudo unzip idn2 libcap2-bin dns-root-data libcap2 netcat-openbsd procps) PIHOLE_DEPS=(cron curl iputils-ping psmisc sudo unzip idn2 libcap2-bin dns-root-data libcap2 netcat-openbsd procps)
# Packages required for the Web admin interface (stored as an array) # Packages required for the Web admin interface (stored as an array)
@ -419,32 +427,74 @@ select_rpm_php(){
rpm -q ${REMI_PKG} &> /dev/null || rc=$? rpm -q ${REMI_PKG} &> /dev/null || rc=$?
if [[ $rc -ne 0 ]]; then if [[ $rc -ne 0 ]]; then
# The PHP version available via default repositories is older than version 7 # The PHP version available via default repositories is older than version 7
if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" "${r}" "${c}"; then dialog --no-shadow --clear \
# User decided to NOT update PHP from REMI, attempt to install the default available PHP version --title "PHP 7 Update (recommended)" \
printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}" --defaultno \
: # continue with unsupported php version --yesno "PHP 7.x is recommended for both security and language features. \
else \\nWould you like to install PHP7 via Remi's RPM repository? \
printf " %b Enabling Remi's RPM repository (https://rpms.remirepo.net)\\n" "${INFO}" \\n\\nSee: https://rpms.remirepo.net for more information" \
"${PKG_INSTALL[@]}" "https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" &> /dev/null "${r}" "${c}"
# enable the PHP 7 repository via yum-config-manager (provided by yum-utils)
"${PKG_INSTALL[@]}" "yum-utils" &> /dev/null result=$?
yum-config-manager --enable ${REMI_REPO} &> /dev/null case ${result} in
printf " %b Remi's RPM repository has been enabled for PHP7\\n" "${TICK}" # User chose to install PHP 7 via Remi's RPM repository
# trigger an install/update of PHP to ensure previous version of PHP is updated from REMI "${DIALOG_OK}")
if "${PKG_INSTALL[@]}" "php-cli" &> /dev/null; then printf " %b Enabling Remi's RPM repository (https://rpms.remirepo.net)\\n" "${INFO}"
printf " %b PHP7 installed/updated via Remi's RPM repository\\n" "${TICK}" "${PKG_INSTALL[@]}" "https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" &> /dev/null
else # enable the PHP 7 repository via yum-config-manager (provided by yum-utils)
printf " %b There was a problem updating to PHP7 via Remi's RPM repository\\n" "${CROSS}" "${PKG_INSTALL[@]}" "yum-utils" &> /dev/null
yum-config-manager --enable ${REMI_REPO} &> /dev/null
printf " %b Remi's RPM repository has been enabled for PHP7\\n" "${TICK}"
# trigger an install/update of PHP to ensure previous version of PHP is updated from REMI
if "${PKG_INSTALL[@]}" "php-cli" &> /dev/null; then
printf " %b PHP7 installed/updated via Remi's RPM repository\\n" "${TICK}"
else
printf " %b There was a problem updating to PHP7 via Remi's RPM repository\\n" "${CROSS}"
exit 1
fi
;;
# User chose not to install PHP 7 via Remi's RPM repository
"${DIALOG_CANCEL}")
# User decided to NOT update PHP from REMI, attempt to install the default available PHP version
printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}"
;;
# User closed the dialog window
"${DIALOG_ESC}")
printf " %b Escape pressed, exiting installer at Remi dialog window\\n" "${CROSS}"
exit 1 exit 1
fi ;;
fi esac
fi # Warn user of unsupported version of Fedora or CentOS
if ! whiptail --defaultno --title "Unsupported RPM based distribution" --yesno "Would you like to continue installation on an unsupported RPM based distribution?\\n\\nPlease ensure the following packages have been installed manually:\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" "${r}" "${c}"; then
printf " %b Aborting installation due to unsupported RPM based distribution\\n" "${CROSS}"
exit
else
printf " %b Continuing installation with unsupported RPM based distribution\\n" "${INFO}"
fi fi
# Warn user of unsupported version of Fedora or CentOS
dialog --no-shadow --clear \
--title "Unsupported RPM based distribution" \
--defaultno \
--no-button "Exit" \
--yes-button "Continue" \
--yesno "Would you like to continue installation on an unsupported RPM based distribution? \
\\n\\nPlease ensure the following packages have been installed manually: \
\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" \
"${r}" "${c}"
result=$?
case ${result} in
# User chose to continue installation on an unsupported RPM based distribution
"${DIALOG_OK}")
printf " %b User opted to continue installation on an unsupported RPM based distribution.\\n" "${INFO}"
;;
# User chose not to continue installation on an unsupported RPM based distribution
"${DIALOG_CANCEL}")
printf " %b User opted not to continue installation on an unsupported RPM based distribution.\\n" "${INFO}"
exit 1
;;
"${DIALOG_ESC}")
printf " %b Escape pressed, exiting installer at unsupported RPM based distribution dialog window\\n" "${CROSS}"
exit 1
;;
esac
fi fi
fi fi
} }
@ -636,40 +686,46 @@ get_available_interfaces() {
# A function for displaying the dialogs the user sees when first running the installer # A function for displaying the dialogs the user sees when first running the installer
welcomeDialogs() { welcomeDialogs() {
# Display the welcome dialog using an appropriately sized window via the calculation conducted earlier in the script # Display the welcome dialog using an appropriately sized window via the calculation conducted earlier in the script
whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" "${r}" "${c}" dialog --no-shadow --clear \
--backtitle "Welcome" \
# Request that users donate if they enjoy the software since we all work on it in our free time --title "Pi-hole Automated Installer" \
whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: https://pi-hole.net/donate/" "${r}" "${c}" --msgbox "\\n\\nThis installer will transform your device into a network-wide ad blocker!" \
"${r}" "${c}" \
# Explain the need for a static address --and-widget \
if whiptail --defaultno --backtitle "Initiating network interface" --title "Static IP Needed" --yesno "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. --backtitle "Support Pi-hole" \
--title "Open Source Software" \
IMPORTANT: If you have not already done so, you must ensure that this device has a static IP. Either through DHCP reservation, or by manually assigning one. Depending on your operating system, there are many ways to achieve this. --msgbox "\\n\\nThe Pi-hole is free, but powered by your donations: https://pi-hole.net/donate/" \
"${r}" "${c}" \
Choose yes to indicate that you have understood this message, and wish to continue" "${r}" "${c}"; then --and-widget \
#Nothing to do, continue --colors \
echo --backtitle "Initiating network interface" \
else --title "Static IP Needed" \
printf " %b Installer exited at static IP message.\\n" "${INFO}" --no-button "Exit" --yes-button "Continue" \
exit 1 --defaultno \
fi --yesno "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly.\\n\\n \
\\Zb\\Z1IMPORTANT:\\Zn If you have not already done so, you must ensure that this device has a static IP.\\n \
Depending on your operating system, there are many ways to achieve this, through DHCP reservation, or by manually assigning one.\\n\\n \
Please continue when the static addressing has been configured." \
"${r}" "${c}"
result=$?
case "${result}" in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %b Installer exited at static IP message.\\n" "${INFO}"
exit 1
;;
esac
} }
# A function that lets the user pick an interface to use with Pi-hole # A function that lets the user pick an interface to use with Pi-hole
chooseInterface() { chooseInterface() {
# Turn the available interfaces into an array so it can be used with a whiptail dialog # Turn the available interfaces into a string so it can be used with dialog
local interfacesArray=() local interfacesList
# Number of available interfaces # Number of available interfaces
local interfaceCount local interfaceCount
# Whiptail variable storage
local chooseInterfaceCmd
# Temporary Whiptail options storage
local chooseInterfaceOptions
# Loop sentinel variable
local firstLoop=1
# Find out how many interfaces are available to choose from # POSIX compliant way to get the number of elements in an array
interfaceCount=$(wc -l <<< "${availableInterfaces}") interfaceCount=$(printf "%s\n" "${availableInterfaces}" | wc -l)
# If there is one interface, # If there is one interface,
if [[ "${interfaceCount}" -eq 1 ]]; then if [[ "${interfaceCount}" -eq 1 ]]; then
@ -677,33 +733,32 @@ chooseInterface() {
PIHOLE_INTERFACE="${availableInterfaces}" PIHOLE_INTERFACE="${availableInterfaces}"
# Otherwise, # Otherwise,
else else
# Set status for the first entry to be selected
status="ON"
# While reading through the available interfaces # While reading through the available interfaces
while read -r line; do for interface in ${availableInterfaces}; do
# Use a variable to set the option as OFF to begin with # Put all these interfaces into a string
mode="OFF" interfacesList="${interfacesList}${interface} available ${status} "
# If it's the first loop, # All further interfaces are deselected
if [[ "${firstLoop}" -eq 1 ]]; then status="OFF"
# set this as the interface to use (ON)
firstLoop=0
mode="ON"
fi
# Put all these interfaces into an array
interfacesArray+=("${line}" "available" "${mode}")
# Feed the available interfaces into this while loop
done <<< "${availableInterfaces}"
# The whiptail command that will be run, stored in a variable
chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface (press space to toggle selection)" "${r}" "${c}" 6)
# Now run the command using the interfaces saved into the array
chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) || \
# If the user chooses Cancel, exit
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# For each interface
for desiredInterface in ${chooseInterfaceOptions}; do
# Set the one the user selected as the interface to use
PIHOLE_INTERFACE=${desiredInterface}
# and show this information to the user
printf " %b Using interface: %s\\n" "${INFO}" "${PIHOLE_INTERFACE}"
done done
# shellcheck disable=SC2086
# Disable check for double quote here as we are passing a string with spaces
PIHOLE_INTERFACE=$(dialog --no-shadow --clear --output-fd 1 \
--radiolist "Choose An Interface (press space to toggle selection)" \
${r} ${c} "${interfaceCount}" ${interfacesList})
result=$?
case ${result} in
"${DIALOG_CANCEL}"|"${DIALOG_ESC}")
# Show an error message and exit
printf " %b %s\\n" "${CROSS}" "No interface selected, exiting installer"
exit 1
;;
esac
printf " %b Using interface: %s\\n" "${INFO}" "${PIHOLE_INTERFACE}"
fi fi
} }
@ -789,57 +844,102 @@ getStaticIPv4Settings() {
local ipSettingsCorrect local ipSettingsCorrect
local DHCPChoice local DHCPChoice
# Ask if the user wants to use DHCP settings as their static IP # Ask if the user wants to use DHCP settings as their static IP
# This is useful for users that are using DHCP reservations; then we can just use the information gathered via our functions # This is useful for users that are using DHCP reservations; we can use the information gathered
DHCPChoice=$(whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --menu --separate-output "Do you want to use your current network settings as a static address? \\n DHCPChoice=$(dialog --no-shadow --clear --output-fd 1 \
IP address: ${IPV4_ADDRESS} \\n --backtitle "Calibrating network interface" \
Gateway: ${IPv4gw} \\n" "${r}" "${c}" 3\ --title "Static IP Address" \
"Yes" "Set static IP using current values" \ --menu "Do you want to use your current network settings as a static address?\\n \
"No" "Set static IP using custom values" \ IP address: ${IPV4_ADDRESS}\\n \
"Skip" "I will set a static IP later, or have already done so" 3>&2 2>&1 1>&3) || \ Gateway: ${IPv4gw}\\n" \
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } "${r}" "${c}" 3 \
"Yes" "Set static IP using current values" \
case ${DHCPChoice} in "No" "Set static IP using custom values" \
"Yes") "Skip" "I will set a static IP later, or have already done so")
# If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict.
whiptail --msgbox --backtitle "IP information" --title "FYI: IP Conflict" "It is possible your router could still try to assign this IP to a device, which would cause a conflict. But in most cases the router is smart enough to not do that. result=$?
If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want. case ${result} in
It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." "${r}" "${c}" "${DIALOG_CANCEL}" | "${DIALOG_ESC}")
# Nothing else to do since the variables are already set above printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
setDHCPCD exit 1
;; ;;
esac
"No")
# Otherwise, we need to ask the user to input their desired settings. case ${DHCPChoice} in
# Start by getting the IPv4 address (pre-filling it with info gathered from DHCP) "Skip")
# Start a loop to let the user enter their information with the chance to go back and edit it if necessary return
until [[ "${ipSettingsCorrect}" = True ]]; do ;;
"Yes")
# Ask for the IPv4 address # If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict.
IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" "${r}" "${c}" "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \ dialog --no-shadow --clear \
# Canceling IPv4 settings window --backtitle "IP information" \
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; } --title "FYI: IP Conflict" \
printf " %b Your static IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}" --msgbox "\\nIt is possible your router could still try to assign this IP to a device, which would cause a conflict. \
But in most cases the router is smart enough to not do that. \
# Ask for the gateway If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want. \
IPv4gw=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 gateway (router)" --inputbox "Enter your desired IPv4 default gateway" "${r}" "${c}" "${IPv4gw}" 3>&1 1>&2 2>&3) || \ It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." \
# Canceling gateway settings window "${r}" "${c}"
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
printf " %b Your static IPv4 gateway: %s\\n" "${INFO}" "${IPv4gw}" result=$?
case ${result} in
# Give the user a chance to review their settings before moving on "${DIALOG_CANCEL}" | "${DIALOG_ESC}")
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Are these settings correct? printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
IP address: ${IPV4_ADDRESS} exit 1
Gateway: ${IPv4gw}" "${r}" "${c}"; then ;;
esac
;;
"No")
# Otherwise, we need to ask the user to input their desired settings.
# Start by getting the IPv4 address (pre-filling it with info gathered from DHCP)
# Start a loop to let the user enter their information with the chance to go back and edit it if necessary
ipSettingsCorrect=false
until [[ "${ipSettingsCorrect}" = True ]]; do
# Ask for the IPv4 address
_staticIPv4Temp=$(dialog --no-shadow --clear --output-fd 1 \
--backtitle "Calibrating network interface" \
--title "IPv4 Address" \
--form "\\nEnter your desired IPv4 address" \
"${r}" "${c}" 0 \
"IPv4 Address:" 1 1 "${IPV4_ADDRESS}" 1 15 19 0 \
"IPv4 Gateway:" 2 1 "${IPv4gw}" 2 15 19 0)
result=$?
case ${result} in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
IPV4_ADDRESS=${_staticIPv4Temp%$'\n'*}
IPv4gw=${_staticIPv4Temp#*$'\n'}
# Give the user a chance to review their settings before moving on
dialog --no-shadow --clear \
--backtitle "Calibrating network interface" \
--title "Static IP Address" \
--defaultno \
--yesno "Are these settings correct?
IP address: ${IPV4_ADDRESS}
Gateway: ${IPv4gw}" \
"${r}" "${c}"
result=$?
case ${result} in
"${DIALOG_OK}")
# After that's done, the loop ends and we move on # After that's done, the loop ends and we move on
ipSettingsCorrect=True ipSettingsCorrect=True
else ;;
# If the settings are wrong, the loop continues "${DIALOG_CANCEL}" | "${DIALOG_ESC}")
ipSettingsCorrect=False printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
fi exit 1
;;
esac
done done
setDHCPCD ;;
;; esac
esac setDHCPCD
} }
# Configure networking via dhcpcd # Configure networking via dhcpcd
@ -929,11 +1029,18 @@ setDNS() {
DNSChooseOptions[DNSServerCount]="" DNSChooseOptions[DNSServerCount]=""
# Restore the IFS to what it was # Restore the IFS to what it was
IFS=${OIFS} IFS=${OIFS}
# In a whiptail dialog, show the options # In a dialog, show the options
DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." "${r}" "${c}" 7 \ DNSchoices=$(dialog --no-shadow --clear --output-fd 1 \
"${DNSChooseOptions[@]}" 2>&1 >/dev/tty) || \ --menu "Select Upstream DNS Provider. To use your own, select Custom." "${r}" "${c}" 7 \
# Exit if the user selects "Cancel" "${DNSChooseOptions[@]}")
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
result=$?
case ${result} in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
# Depending on the user's choice, set the GLOBAL variables to the IP of the respective provider # Depending on the user's choice, set the GLOBAL variables to the IP of the respective provider
if [[ "${DNSchoices}" == "Custom" ]] if [[ "${DNSchoices}" == "Custom" ]]
@ -947,7 +1054,7 @@ setDNS() {
# If the first and second upstream servers do not exist, do not prepopulate an IP address # If the first and second upstream servers do not exist, do not prepopulate an IP address
prePopulate="" prePopulate=""
else else
# Otherwise, prepopulate the whiptail dialogue with the appropriate DNS value(s) # Otherwise, prepopulate the dialogue with the appropriate DNS value(s)
prePopulate=", ${PIHOLE_DNS_2}" prePopulate=", ${PIHOLE_DNS_2}"
fi fi
elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then
@ -957,8 +1064,21 @@ setDNS() {
fi fi
# Prompt the user to enter custom upstream servers # Prompt the user to enter custom upstream servers
piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma. If you want to specify a port other than 53, separate it with a hash.\\n\\nFor example '8.8.8.8, 8.8.4.4' or '127.0.0.1#5335'" "${r}" "${c}" "${prePopulate}" 3>&1 1>&2 2>&3) || \ piholeDNS=$(dialog --no-shadow --clear --output-fd 1 \
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } --backtitle "Specify Upstream DNS Provider(s)" \
--inputbox "Enter your desired upstream DNS provider(s), separated by a comma. \
If you want to specify a port other than 53, separate it with a hash. \
\\n\\nFor example '8.8.8.8, 8.8.4.4' or '127.0.0.1#5335'" \
"${r}" "${c}" "${prePopulate}")
result=$?
case ${result} in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
# Clean user input and replace whitespace with comma. # Clean user input and replace whitespace with comma.
piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}") piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}")
@ -977,7 +1097,21 @@ setDNS() {
# If either of the DNS servers are invalid, # If either of the DNS servers are invalid,
if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then
# explain this to the user, # explain this to the user,
whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\\n\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} dialog --no-shadow --clear \
--title "Invalid IP Address(es)" \
--backtitle "Invalid IP" \
--msgbox "\\nOne or both of the entered IP addresses were invalid. Please try again. \
\\n\\nInvalid IPs: ${PIHOLE_DNS_1}, ${PIHOLE_DNS_2}" \
"${r}" "${c}"
result=$?
case ${result} in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
# set the variables back to nothing, # set the variables back to nothing,
if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then
PIHOLE_DNS_1="" PIHOLE_DNS_1=""
@ -988,12 +1122,25 @@ setDNS() {
# and continue the loop. # and continue the loop.
DNSSettingsCorrect=False DNSSettingsCorrect=False
else else
# Otherwise, show the DNS setting to the user, and break the loop if they confirm them. dialog --no-shadow --clear \
if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" "${r}" "${c}"); then --backtitle "Specify Upstream DNS Provider(s)" \
DNSSettingsCorrect=True --title "Upstream DNS Provider(s)" \
else --yesno "Are these settings correct?\\n\\tDNS Server 1:\\t${PIHOLE_DNS_1}\\n\\tDNS Server 2:\\t${PIHOLE_DNS_2}" \
DNSSettingsCorrect=False "${r}" "${c}"
fi
result=$?
case ${result} in
"${DIALOG_OK}")
DNSSettingsCorrect=True
;;
"${DIALOG_CANCEL}")
DNSSettingsCorrect=False
;;
"${DIALOG_ESC}")
printf " %bEscape pressed, exiting installer at DNS Settings%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
fi fi
done done
else else
@ -1023,106 +1170,122 @@ setDNS() {
# Allow the user to enable/disable logging # Allow the user to enable/disable logging
setLogging() { setLogging() {
# Local, named variables # Ask the user if they want to enable logging
local LogToggleCommand dialog --no-shadow --clear \
local LogChooseOptions --backtitle "Pihole Installation" \
local LogChoices --title "Enable Logging" \
--yesno "\\n\\nWould you like to enable query logging?" \
# Ask if the user wants to log queries "${r}" "${c}"
LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries?" "${r}" "${c}" 6)
# The default selection is on result=$?
LogChooseOptions=("On (Recommended)" "" on case ${result} in
Off "" off) "${DIALOG_OK}")
# Get the user's choice # If they chose yes,
LogChoices=$("${LogToggleCommand[@]}" "${LogChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) printf " %b Query Logging on.\\n" "${INFO}"
case ${LogChoices} in
# If it's on,
"On (Recommended)")
printf " %b Logging On.\\n" "${INFO}"
# set the GLOBAL variable setting to true
QUERY_LOGGING=true QUERY_LOGGING=true
;; ;;
# Otherwise, it's off, "${DIALOG_CANCEL}")
Off) # If they chose no,
printf " %b Logging Off.\\n" "${INFO}" printf " %b Query Logging off.\\n" "${INFO}"
# set the GLOBAL variable setting to false
QUERY_LOGGING=false QUERY_LOGGING=false
;; ;;
"${DIALOG_ESC}")
# User pressed <ESC>
printf " %bEscape pressed, exiting installer at Query Logging choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac esac
} }
# Allow the user to set their FTL privacy level # Allow the user to set their FTL privacy level
setPrivacyLevel() { setPrivacyLevel() {
local LevelCommand PRIVACY_LEVEL=$(dialog --no-shadow --clear --output-fd 1 \
local LevelOptions --radiolist "Select a privacy mode for FTL. https://docs.pi-hole.net/ftldns/privacylevels/" \
"${r}" "${c}" 6 \
LevelCommand=(whiptail --separate-output --radiolist "Select a privacy mode for FTL. https://docs.pi-hole.net/ftldns/privacylevels/" "${r}" "${c}" 6) # The default selection is level 0
"0" "Show everything" on \
# The default selection is level 0 "1" "Hide domains" off \
LevelOptions=( "2" "Hide domains and clients" off \
"0" "Show everything" on "3" "Anonymous mode" off)
"1" "Hide domains" off
"2" "Hide domains and clients" off result=$?
"3" "Anonymous mode" off case ${result} in
) "${DIALOG_OK}")
printf " %b Using privacy level: %s\\n" "${INFO}" "${PRIVACY_LEVEL}"
# Get the user's choice ;;
PRIVACY_LEVEL=$("${LevelCommand[@]}" "${LevelOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1) "${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %b Cancelled privacy level selection.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
printf " %b Privacy level %d" "${INFO}" "${PRIVACY_LEVEL}" exit 1
;;
esac
} }
# Function to ask the user if they want to install the dashboard # Function to ask the user if they want to install the dashboard
setAdminFlag() { setAdminFlag() {
# Local, named variables
local WebToggleCommand
local WebChooseOptions
local WebChoices
# Similar to the logging function, ask what the user wants # Similar to the logging function, ask what the user wants
WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web admin interface?" "${r}" "${c}" 6) dialog --no-shadow --clear \
# with the default being enabled --backtitle "Pihole Installation" \
WebChooseOptions=("On (Recommended)" "" on --title "Admin Web Interface" \
Off "" off) --yesno "\\n\\nDo you want to install the Admin Web Interface?" \
WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) "${r}" "${c}"
# Depending on their choice
case ${WebChoices} in result=$?
"On (Recommended)") case ${result} in
printf " %b Web Interface On\\n" "${INFO}" "${DIALOG_OK}")
# Set it to true # If they chose yes,
printf " %b Installing Admin Web Interface\\n" "${INFO}"
# Set the flag to install the web interface
INSTALL_WEB_INTERFACE=true INSTALL_WEB_INTERFACE=true
;; ;;
Off) "${DIALOG_CANCEL}")
printf " %b Web Interface Off\\n" "${INFO}" # If they chose no,
# or false printf " %b Not installing Admin Web Interface\\n" "${INFO}"
# Set the flag to not install the web interface
INSTALL_WEB_INTERFACE=false INSTALL_WEB_INTERFACE=false
# Deselect the web server as well, since it is obsolete then
INSTALL_WEB_SERVER=false INSTALL_WEB_SERVER=false
;; ;;
"${DIALOG_ESC}")
# User pressed <ESC>
printf " %bEscape pressed, exiting installer at Admin Web Interface choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac esac
# If the user wants to install the Web admin interface (i.e. it has not been deselected above) # If the user wants to install the Web admin interface (i.e. it has not been deselected above)
if [[ "${INSTALL_WEB_SERVER}" == true ]]; then if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
# Get list of required PHP modules, excluding base package (common) and handler (cgi) # Get list of required PHP modules, excluding base package (common) and handler (cgi)
local i php_modules local i php_modules
for i in "${PIHOLE_WEB_DEPS[@]}"; do [[ $i == 'php'* && $i != *'-common' && $i != *'-cgi' ]] && php_modules+=" ${i#*-}"; done for i in "${PIHOLE_WEB_DEPS[@]}"; do [[ $i == 'php'* && $i != *'-common' && $i != *'-cgi' ]] && php_modules+=" ${i#*-}"; done
WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web server (lighttpd) and required PHP modules?\\n\\nNB: If you disable this, and, do not have an existing web server and required PHP modules (${php_modules# }) installed, the web interface will not function. Additionally the web server user needs to be member of the \"pihole\" group for full functionality." "${r}" "${c}" 6) dialog --no-shadow --clear \
# Enable as default and recommended option --backtitle "Pi-hole Installation" \
WebChooseOptions=("On (Recommended)" "" on --title "Web Server" \
Off "" off) --yesno "\\n\\nA web server is required for the Admin Web Interface. \
WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) \\n\\nDo you want to install lighttpd and the required PHP modules? \
# Depending on their choice \\n\\nNB: If you disable this, and, do not have an existing web server \
case ${WebChoices} in and required PHP modules (${php_modules# }) installed, the web interface \
"On (Recommended)") will not function. Additionally the web server user needs to be member of \
printf " %b Web Server On\\n" "${INFO}" the \"pihole\" group for full functionality." \
# set it to true, as clearly seen below. "${r}" "${c}"
result=$?
case ${result} in
"${DIALOG_OK}")
# If they chose yes,
printf " %b Installing lighttpd\\n" "${INFO}"
# Set the flag to install the web server
INSTALL_WEB_SERVER=true INSTALL_WEB_SERVER=true
;; ;;
Off) "${DIALOG_CANCEL}")
printf " %b Web Server Off\\n" "${INFO}" # If they chose no,
# or false printf " %b Not installing lighttpd\\n" "${INFO}"
# Set the flag to not install the web server
INSTALL_WEB_SERVER=false INSTALL_WEB_SERVER=false
;; ;;
"${DIALOG_ESC}")
# User pressed <ESC>
printf " %bEscape pressed, exiting installer at web server choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac esac
fi fi
} }
@ -1133,18 +1296,33 @@ chooseBlocklists() {
if [[ -f "${adlistFile}" ]]; then if [[ -f "${adlistFile}" ]]; then
mv "${adlistFile}" "${adlistFile}.old" mv "${adlistFile}" "${adlistFile}.old"
fi fi
# Let user select (or not) blocklists via a checklist # Let user select (or not) blocklists
cmd=(whiptail --separate-output --checklist "Pi-hole relies on third party lists in order to block ads.\\n\\nYou can use the suggestion below, and/or add your own after installation\\n\\nTo deselect the suggested list, use spacebar" "${r}" "${c}" 5) dialog --no-shadow --clear \
# In an array, show the options available (all off by default): --backtitle "Pi-hole Installation" \
options=(StevenBlack "StevenBlack's Unified Hosts List" on) --title "Blocklists" \
--yesno "\\nPi-hole relies on third party lists in order to block ads. \
# In a variable, show the choices available; exit if Cancel is selected \\n\\nYou can use the suggestion below, and/or add your own after installation. \
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; rm "${adlistFile}" ;exit 1; } \\n\\nSelect 'Yes' to include: \
# Add all selected choices to the lists file \\n\\nStevenBlack's Unified Hosts List" \
for choice in ${choices} "${r}" "${c}"
do
appendToListsFile "${choice}" result=$?
done case ${result} in
"${DIALOG_OK}")
# If they chose yes,
printf " %b Installing StevenBlack's Unified Hosts List\\n" "${INFO}"
echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}"
;;
"${DIALOG_CANCEL}")
# If they chose no,
printf " %b Not installing StevenBlack's Unified Hosts List\\n" "${INFO}"
;;
"${DIALOG_ESC}")
# User pressed <ESC>
printf " %bEscape pressed, exiting installer at blocklist choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
# Create an empty adList file with appropriate permissions. # Create an empty adList file with appropriate permissions.
if [ ! -f "${adlistFile}" ]; then if [ ! -f "${adlistFile}" ]; then
install -m 644 /dev/null "${adlistFile}" install -m 644 /dev/null "${adlistFile}"
@ -1153,14 +1331,6 @@ chooseBlocklists() {
fi fi
} }
# Accept a string parameter, it must be one of the default lists
# This function saves duplication between chooseBlocklists and installDefaultBlocklists
appendToListsFile() {
case $1 in
StevenBlack ) echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}";;
esac
}
# Used only in unattended setup # Used only in unattended setup
# If there is already the adListFile, we keep it, else we create it using all default lists # If there is already the adListFile, we keep it, else we create it using all default lists
installDefaultBlocklists() { installDefaultBlocklists() {
@ -1169,7 +1339,7 @@ installDefaultBlocklists() {
if [[ -f "${adlistFile}" ]]; then if [[ -f "${adlistFile}" ]]; then
return; return;
fi fi
appendToListsFile StevenBlack echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}"
} }
# Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory # Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory
@ -1940,14 +2110,14 @@ Your Admin Webpage login password is ${pwstring}"
fi fi
# Final completion message to user # Final completion message to user
whiptail --msgbox --backtitle "Make it so." --title "Installation Complete!" "Configure your devices to use the Pi-hole as their DNS server using: dialog --no-shadow --clear \
--title "Installation Complete!" \
IPv4: ${IPV4_ADDRESS%/*} --msgbox "Configure your devices to use the Pi-hole as their DNS server using: \
IPv6: ${IPV6_ADDRESS:-"Not Configured"} \\n\\nIPv4: ${IPV4_ADDRESS%/*} \
\\nIPv6: ${IPV6_ADDRESS:-"Not Configured"} \
If you have not done so already, the above IP should be set to static. \\nIf you have not done so already, the above IP should be set to static. \
\\n${additional}"
${additional}" "${r}" "${c}" "${r}" "${c}"
} }
update_dialogs() { update_dialogs() {
@ -1967,20 +2137,32 @@ update_dialogs() {
opt2b="Resets Pi-hole and allows re-selecting settings." opt2b="Resets Pi-hole and allows re-selecting settings."
# Display the information to the user # Display the information to the user
UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" "${r}" "${c}" 2 \ UpdateCmd=$(dialog --no-shadow --clear --output-fd 1 \
--title "Existing Install Detected!" \
--menu "\\n\\nWe have detected an existing install. \
\\n\\nPlease choose from the following options: \
\\n($strAdd)" \
"${r}" "${c}" 2 \
"${opt1a}" "${opt1b}" \ "${opt1a}" "${opt1b}" \
"${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \ "${opt2a}" "${opt2b}")
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
result=$?
case ${result} in
"${DIALOG_CANCEL}" | "${DIALOG_ESC}")
printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
exit 1
;;
esac
# Set the variable based on if the user chooses # Set the variable based on if the user chooses
case ${UpdateCmd} in case ${UpdateCmd} in
# repair, or # repair, or
${opt1a}) "${opt1a}")
printf " %b %s option selected\\n" "${INFO}" "${opt1a}" printf " %b %s option selected\\n" "${INFO}" "${opt1a}"
useUpdateVars=true useUpdateVars=true
;; ;;
# reconfigure, # reconfigure,
${opt2a}) "${opt2a}")
printf " %b %s option selected\\n" "${INFO}" "${opt2a}" printf " %b %s option selected\\n" "${INFO}" "${opt2a}"
useUpdateVars=false useUpdateVars=false
;; ;;
@ -2478,7 +2660,7 @@ main() {
if [[ -f "${setupVars}" ]]; then if [[ -f "${setupVars}" ]]; then
# if it's running unattended, # if it's running unattended,
if [[ "${runUnattended}" == true ]]; then if [[ "${runUnattended}" == true ]]; then
printf " %b Performing unattended setup, no whiptail dialogs will be displayed\\n" "${INFO}" printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}"
# Use the setup variables # Use the setup variables
useUpdateVars=true useUpdateVars=true
# also disable debconf-apt-progress dialogs # also disable debconf-apt-progress dialogs

Loading…
Cancel
Save