Zerocat’s Coreboot-Machines  v0.14.0
How to create Zerocat Products like ZC-X200t, ZC-X230t, and others...
setup-parabola.sh File Reference

Drop-in replacement for the poor, original install script of the Parabola GNU/Linux-libre Live System (LXDE/OpenRC/2020-08-03). More...

Detailed Description

Utility Script: Set up Parabola GNU/Linux-libre

This script helps you to set up Parabola GNU/Linux-libre, using standard or encrypted partitioning schemes (including encrypted Swap). As long as usage of the OpenRC Init System is broken due to conflicting dependencies, the script suggests to use SystemD as a workaround.

During development, the How-tos provided by Parabola, Arch-Linux and Libreboot have been an essential source of information, e.g.:

Target Machines

The script has been tested on Zerocat’s Coreboot Machines. These are configured to have a GRUB2 Payload available on chip, they do not require to have the GRUB2 Bootloader installed on disk.

Nevertheless, the script optionally offers to install the GRUB2 Bootloader into the Master Boot Record (MBR) of your selected drive, but this feature has not been tested, yet.

The script provides a variety of partitioning schemes, using standard or LUKS1-encrypted partitions. Please note that the Zerocat Bootmenu is capable of booting these schemes via GRUB2 Configuration File, which is located on disk. Via fallback menu entry, you can search for the Kernel Linux-libre directly, in case your configuration file gets corrupted or lost. However, separate Boot-Partitions are not yet supported this way.

Invocation Example

On a fresh boot of the Parabola-LXDE-OpenRC Live System, run:

./setup-parabola.sh

Script Code

#!/bin/bash
##>! @file
##>! @cond
#

# Zerocat Coreboot-Machines --- Create Zerocat Coreboot Images
#
# Copyright (C) 2021 Kai Mertens <kmx@posteo.net>
#
# The Zerocat Coreboot-Machines Project is free software: you can redistribute
# it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# The Zerocat Coreboot-Machines Project is distributed in the hope that it
# will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# This file is part of the Zerocat Coreboot-Machines Project.
#
# This script will help you to install the Parabola GNU/Linux-libre
# System on a Corebooted Zerocat Machine with GRUB2 as a Payload:
#
# 1. get the ISO-image
#    Website:   https://wiki.parabola.nu/Get_Parabola#Parabola_OpenRC_LXDE_ISO
#    ISO file:  parabola-dual-openrc-lxde-2020.08.03-netinstall.iso
# 2. start the live session
# 3. copy this script into the live account and grant permisson for execution
# 4. run this script
# 5. reboot
#
# This script is a reviewed and (hopefully) improved version of the
# original Parabola Installation CLI, checked out at:
#
# git://git.parabola.nu/packages/parabolaiso.git
#
# tag name v46.1 (f29d8dafa7e2a3f2010909ffd96bb899f25ccacb)
# tag date 2020-08-03 13:12:27 -0400
# tagged by David P <megver83@parabola.nu>
# commit 231f35c3c4ae7a1cf073e67f6ae091d1f1053a7c
#
# Within the parabolaiso repository, see AUTHORS.rst and LICENSE for
# proper authorship and license of the original sources, e.g.:
#
# parabolaiso/configs/lxde-openrc/airootfs/root/.scriptsInstallation/language/en/install.sh
# parabolaiso/configs/lxde-openrc/airootfs/root/.scriptsInstallation/language/en/systemConfig.sh
# parabolaiso/configs/lxde-openrc/airootfs/root/.scriptsInstallation/language/en/userAccount.sh
# parabolaiso/configs/lxde-openrc/airootfs/root/.scriptsInstallation/x11.sh

welcome() {

  $DIALOG ${FLAGS_DIALOG[@]} \
    --msgbox \
      "\
                                                                            \n\
# Welcome                                                                   \n\
                                                                            \n\
This is Zerocat’s install script for Parabola GNU/Linux-libre. \
It should be run on a fresh boot of the Parabola Live System \
instead of the original install scripts. Please activate an \
internet connection, first.                                                 \n\
                                                                            \n\
# WWW Resources                                                             \n\
                                                                            \n\
* Website:  https://wiki.parabola.nu/Get_Parabola#Parabola_OpenRC_LXDE_ISO  \n\
* ISO:      parabola-dual-openrc-lxde-2020.08.03-netinstall.iso             \n\
                                                                            \n\
Good Luck! – www.zerocat.org                                                \n\
" \
      ${WIDGET_DIM};
}

fillscreen() {
  # Fill stdout with empty lines such that dialog and script output
  # won't overlap.

  echo "Fill screen ..."
  echo -e \
    "\n\n\n\n\n\n\n\n\n\n" \
    "\n\n\n\n\n\n\n\n\n\n" \
    "\n\n\n\n\n\n\n\n\n\n" \
    "\n\n\n\n\n\n\n\n\n\n" \
    "\n\n\n\n\n\n\n\n\n\n";
  echo "... done."
}

checkperm() {
  echo "Check priviledges ..."
  if [ "$EUID" -ne 0 ]; then
    echo "This script requires root priviledges."
    exit 1
  fi
  echo "... done."
}

notool() {
  # $1: tool name
  # let’s use builtin echo command here:
  echo "Tool $1 is missing."
  exit 1
}

hitenter() {

  # positional parameter

  # locals
  local key=''

  read \
    -p'Hit any key to continue, <ESC> to abort: ' \
    -N1 \
    -r \
    -s \
      key
  [ "$key" == $'\e' ] && {
    echo
    return 1
  }
  echo
  echo
  return 0
}

sync_keyrings() {
  local -a keys=(
    "parabola"
    "archlinux"
  )
  [ $(uname -m) = i686 ] && keys+=("archlinux32")

  pacman \
    -Syy ${keys[@]/%/-keyring} \
    --config "$config_pacman_alternate" \
    --noconfirm && \
  pacman-key \
    --config "$config_pacman_alternate" \
    --keyserver "$config_pacman_keyserver" \
    --init && \
  pacman-key \
    --config "$config_pacman_alternate" \
    --keyserver "$config_pacman_keyserver" \
    --populate ${keys[@]} && \
  pacman-key \
    --config "$config_pacman_alternate" \
    --keyserver "$config_pacman_keyserver" \
    --refresh-keys

  return $?
}

set_DISK_SYSTEM() {

  # positional parameter

  # local vars
  local i
  local -i n=1
  local -a list_of_disks=()
  local -a menulist_disk=()
  local feedback

  # collect available disks
  list_of_disks=( \
    $( \
      udevadm settle && \
      lsblk -n --nodeps -oPATH,TYPE | \
      egrep disk | \
      cut -f1 -d' ' - \
    ) \
  )

  # select a disk
  for i in "${list_of_disks[@]}"; do
    menulist_disk+=("${n}" "${i}")
    n+=1
  done
  feedback=$( \
    $DIALOG ${FLAGS_DIALOG[@]} \
      --cancel-label "Abort" \
      --menu "Select Disk" ${MENUWIDGET_DIM} "${menulist_disk[@]}" \
  )
  case $? in
    0)
      DISK_SYSTEM=${menulist_disk[$((feedback*2-1))]}
      FLAG_DISK='on'
      $DIALOG ${FLAGS_DIALOG[@]} \
        --msgbox "Selected Disk is: ${DISK_SYSTEM}" ${WIDGET_DIM}
      ;;
    *)
      echo; echo;
      abort
      ;;
  esac
}

open_encryption() {

  # positional parameter

  # locals
  local -r -a crypto_LUKS=( \
    $( \
      lsblk -n -oPATH,FSTYPE | \
      egrep ${DISK_SYSTEM} | \
      egrep crypto_LUKS | \
      cut -f1 -d' ' - \
    ) \
  )
  local n

  for n in "${crypto_LUKS[@]}"; do
    cryptsetup luksOpen "${n}" "${n##*/}${CRYPT_SUFFIX}"
  done
}

assign_mountpoints() {

  # positional parameter

  # locals
  local i
  local -i n
  local -a list_of_vol
  local -a menulist_vol
  local feedback
  local partition
  local mountpoint
  local device_cryptSWAP

  # dismount
  dismount_mountpoints

  while [ true ]; do
    # update list of volumes
    list_of_vol=( \
      $(echo \
"$( \
  udevadm settle && \
  lsblk -n -oPATH,TYPE,PARTTYPENAME,FSTYPE,MOUNTPOINT,SIZE | \
  egrep "${DISK_SYSTEM##*/}" | \
  egrep -v Extended | \
  egrep -v crypto_LUKS | \
  egrep -e 'part|crypt' | \
  $SED -r -e 's/ /·/g;' - \
)" ) \
    )

    # set menu list, add [cryptSWAP] marker
    n=1
    menulist_vol=()
    device_cryptSWAP=''
    get_device '[cryptSWAP]' mountpoints_assigned partitions_processed device_cryptSWAP
    for i in "${list_of_vol[@]}"; do
      [ -n "$(echo $i | grep ${device_cryptSWAP})" ] && \
        i="${i}·-->·[cryptSWAP]"
      menulist_vol+=("${n}" "${i//·/ }")
      n+=1
    done

    feedback=$( \
      $DIALOG ${FLAGS_DIALOG[@]} \
        --ok-label "Select" \
        --extra-button --extra-label "Done" \
        --cancel-label "Abort" \
        --menu "Select a Partition of Disk \`$DISK_SYSTEM' and assign a mountpoint ...\nFirst select one intended for mountpoint “/mnt/”, then optionally assign subordinary mountpoints to other partitions.\nNote swap formatted partitions can be used for [SWAP], whereas non-formatted Linux partitions shall be used for [cryptSWAP].\nPlease select your Swap carefully, the script does not yet provide a type check." ${MENUWIDGET_DIM} "${menulist_vol[@]}" \
    )
    case $? in
      0)
        partition="${menulist_vol[$((feedback*2-1))]%% *}"
        for i in ${partitions_processed[@]}; do
          [ "$i" == "$partition" ] && {
            $DIALOG ${FLAGS_DIALOG[@]} \
              --msgbox "Partition \`$i' is already used." ${WIDGET_DIM}
            continue 2
          }
        done
        feedback=$( \
          $DIALOG ${FLAGS_DIALOG[@]} \
            --menu "Assign a Mountpoint to Partition \`$partition'" ${MENUWIDGET_DIM} "${menulist_mountpoint[@]}" \
        )
        case $? in
          0)    # OK button
            mountpoint="${menulist_mountpoint[$((feedback*2-1))]}"
            for i in ${mountpoints_assigned[@]}; do
              [ "$i" == "$mountpoint" ] && {
                $DIALOG ${FLAGS_DIALOG[@]} \
                  --msgbox "Mountpoint \`$i' is already assigned." ${WIDGET_DIM}
                continue 2
              }
            done
            if [ "$mountpoint" == '/mnt/' -o -n "$FLAG_ROOT" ]; then
              case "$mountpoint" in
                '[SWAP]')
                  swapon $partition
                  ;;
                '[cryptSWAP]')
                  ;;
                '/mnt/')
                  parted -s $DISK_SYSTEM -- set $(echo $partition | $SED -r -e 's/([a-zA-Z_/-]*)([0-9]+)(.*)/\2/;' -) boot on &> /dev/null
                  mount $partition /mnt &> /dev/null
                  FLAG_ROOT='on'
                  ;;
                '/mnt/usr'|'/mnt/usr/local')
                  mkdir -p ${mountpoint%/} &> /dev/null
                  mount $partition ${mountpoint%/}
                  FLAG_USR='on'
                  ;;
                '/mnt/boot')
                  parted -s $DISK_SYSTEM -- set $(echo $partition | $SED -r -e 's/([a-zA-Z_/-]*)([0-9]+)(.*)/\2/;' -) boot on &> /dev/null
                  mkdir -p ${mountpoint%/} &> /dev/null
                  mount $partition ${mountpoint%/}
                  cd ${mountpoint%/} && ln -sf . boot && cd - &> /dev/null
                  ;;
                *)
                  mkdir -p ${mountpoint%/} &> /dev/null
                  mount $partition ${mountpoint%/}
                  ;;
              esac
              partitions_processed+=("$partition")
              mountpoints_assigned+=("$mountpoint")
              if [ "${partition##*_}" == 'crypt' ]; then
                FLAG_CRYPT='on'
                FLAG_PLAIN=''
              fi
            else
              $DIALOG ${FLAGS_DIALOG[@]} \
                --msgbox "You must assign a partition to the \`/mnt/' mountpoint, first." ${WIDGET_DIM}
            fi
            ;;
        esac
        ;;
      3)
        [ -n "$FLAG_ROOT" ] && {
          echo; echo;
          break
        }
        ;;
      *)
        echo; echo;
        abort
        ;;
    esac
  done
}

disk_operations() {

  # positional parameter

  # locals
  local feedback
  local -a menulist_operation=(
    1   "Wipe Disk with Zeros"
    2   "New Scheme: [MSDOS [2GB-SWAP] [xGB(ext4)]]"
    3   "New Scheme: [MSDOS [20GB(ext4)] [2GB-SWAP] [xGB(ext4)]]"
    4   "New Scheme: [MSDOS [20GB(ext4)] [10GB(ext4)] [2GB-SWAP] [xGB(ext4)]]"
    5   "New Scheme: [MSDOS [500MiB(ext4)] [20GB(ext4)] [2GB-SWAP] [xGB(ext4)]]"
    6   "New Scheme: [MSDOS [xGB(LUKS1(ext4))]]"
    7   "New Scheme: [MSDOS [20GB(LUKS1(ext4))] [xGB(LUKS1(ext4))]]"
    8   "New Scheme: [MSDOS [20GB(LUKS1(ext4))] [2GB-cryptSWAP] [xGB(LUKS1(ext4))]]"
    9   "New Scheme: [MSDOS [20GB(LUKS1(ext4))] [10GB(LUKS1(ext4))] [2GB-cryptSWAP] [xGB(LUKS1(ext4))]]"
    10  "New Scheme: [MSDOS [500MiB(LUKS1(ext4))] [20GB(LUKS1(ext4))] [2GB-cryptSWAP] [xGB(LUKS1(ext4))]]"
    11  "Select Partitions, assign Mountpoints"
  )

  # disk operations
  while [ true ]; do
    feedback=$( \
      $DIALOG ${FLAGS_DIALOG[@]} \
        --cancel-label "Abort" \
        ${FLAG_ROOT:+--extra-button --extra-label "Done"} \
        ${FLAG_ROOT:+--default-button extra} \
        --menu "Disk Operations on Disk \`$DISK_SYSTEM'\nATTENTION! Your data is likely to be erased!" ${MENUWIDGET_DIM} "${menulist_operation[@]}"
    )
    case $? in
      0)
        case $feedback in
          1)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on Disk \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nThis will take some time, sure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free up mountpoints
                dismount_mountpoints

                # Wipe disk
                echo "Wiping disk with zeros ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB status=progress || \
                  catch_error

                # Wait for user to acknowledge
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
                ;;
            esac
            ;;
          2)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on Disk \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free up mountpoints
                dismount_mountpoints

                # Create msdos partition table
                # Create partitions, e.g.: [SWAP] + /
                # Format partitions
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=2000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 2000MiB mkpart primary 2000MiB -1s && \
                echo "Make swap space ..." && \
                (echo t; echo 1; echo 82; echo w) | fdisk $DISK_SYSTEM && \
                mkswap ${DISK_SYSTEM}1 && \
                echo "Create filesystem ..." && \
                mkfs.ext4 ${DISK_SYSTEM}2 && \
                echo "Partitions are now ready to be mounted." || \
                  catch_error

                # Wait for user to acknowledge
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
                ;;
            esac
            ;;
          3)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free up mountpoints
                dismount_mountpoints

                # Create msdos partition table
                # Format Disk, e.g.: / + [SWAP] + /home
                # Format partitions
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=22000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 20000MiB mkpart primary 20000MiB 22000MiB mkpart primary 22000MiB -1s && \
                echo "Create swap space ..." && \
                (echo t; echo 2; echo 82; echo w) | fdisk $DISK_SYSTEM && \
                mkswap ${DISK_SYSTEM}2 && \
                echo "Create filesystems ..." && \
                mkfs.ext4 ${DISK_SYSTEM}1 && \
                mkfs.ext4 ${DISK_SYSTEM}3 && \
                echo "Partitions are now ready to be mounted." || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          4)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Create msdos partition table
                # Format Disk, e.g.: / + /tmp + [SWAP] + /home
                # Format partitions
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=30000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=32000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 20000MiB mkpart primary 20000MiB 30000MiB mkpart primary 30000MiB 32000MiB mkpart primary 32000MiB -1s && \
                echo "Create swap space ..." && \
                (echo t; echo 3; echo 82; echo w) | fdisk $DISK_SYSTEM && \
                mkswap ${DISK_SYSTEM}3 && \
                echo "Create filesystems ..." && \
                mkfs.ext4 ${DISK_SYSTEM}1 && \
                mkfs.ext4 ${DISK_SYSTEM}2 && \
                mkfs.ext4 ${DISK_SYSTEM}4 && \
                echo "Partitions are now ready to be mounted." || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          5)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Create msdos partition table
                # Format Disk, e.g.: /boot + / + [SWAP] + /home
                # Format partitions
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=500 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20500 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=22500 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 500MiB mkpart primary 500MiB 20500MiB mkpart primary 20500MiB 22500MiB mkpart primary 22500MiB -1s && \
                echo "Create swap space ..." && \
                (echo t; echo 3; echo 82; echo w) | fdisk $DISK_SYSTEM && \
                mkswap ${DISK_SYSTEM}3 && \
                echo "Create filesystems ..." && \
                mkfs.ext4 ${DISK_SYSTEM}1 && \
                mkfs.ext4 ${DISK_SYSTEM}2 && \
                mkfs.ext4 ${DISK_SYSTEM}4 && \
                echo "Partitions are now ready to be mounted." || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          6)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Create msdos partition table
                # Format Disk, e.g.: /
                # Setup encryption
                # Open encryption
                # Format partition
                # Close encryption
                echo "Wipe old partition header ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partition ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB -1s && \
                echo "Create LUKS header ..." && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}1 && \
                echo "Open encryption ..." && \
                cryptsetup luksOpen ${DISK_SYSTEM}1 "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                echo "Create filesystem ..." && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                echo "Store disk passphrase at a save place." && \
                sleep $PROCESS_DELAY && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          7)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Write MSDOS partition table
                # Create Partitions, e.g.: / + /home
                # Setup encryption
                # Open encryption
                # Format partitions
                # Close encryption
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 20000MiB mkpart primary 20000MiB -1s && \
                echo "Create LUKS header ..." && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}1 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}2 && \
                echo "Open encryption ..." && \
                cryptsetup luksOpen ${DISK_SYSTEM}1 "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}2 "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                echo "Create filesystems ..." && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                echo "Store disk passphrases at a save place." && \
                sleep $PROCESS_DELAY && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          8)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Write MSDOS partition table
                # Create Partitions, e.g.: / + [cryptSWAP] + /home
                # Setup encryption
                # Open encryption
                # Format partitions
                # Close encryption
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=22000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 20000MiB mkpart primary 20000MiB 22000MiB mkpart primary 22000MiB -1s && \
                echo "Create LUKS header ..." && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}1 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}3 && \
                echo "Open encryption ..." && \
                cryptsetup luksOpen ${DISK_SYSTEM}1 "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}3 "${DISK_SYSTEM##*/}3${CRYPT_SUFFIX}" && \
                echo "Create filesystems ..." && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}3${CRYPT_SUFFIX}" && \
                echo "Store disk passphrases at a save place." && \
                sleep $PROCESS_DELAY && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}3${CRYPT_SUFFIX}" || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          9)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Write MSDOS partition table
                # Create Partitions, e.g.: / + /tmp + [cryptSWAP] + /home
                # Setup encryption
                # Open encryption
                # Format partitions
                # Close encryption
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=30000 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=32000 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 20000MiB mkpart primary 20000MiB 30000MiB mkpart primary 30000MiB 32000MiB mkpart primary 32000MiB -1s && \
                echo "Create LUKS header ..." && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}1 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}2 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}4 && \
                echo "Open encryption ..." && \
                cryptsetup luksOpen ${DISK_SYSTEM}1 "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}2 "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}4 "${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" && \
                echo "Create filesystems ..." && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" && \
                echo "Store disk passphrases at a save place." && \
                sleep $PROCESS_DELAY && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          10)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --default-button no \
              --yesno "Disk Operation on \`$DISK_SYSTEM': \`${menulist_operation[$((feedback*2-1))]}'\n\nSure to proceed?" ${WIDGET_DIM}
            case $? in
              0)
                # Add space on screen
                echo; echo;
                echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
                sleep $PROCESS_DELAY

                # Free /mnt
                dismount_mountpoints

                # Write MSDOS partition table
                # Create Partitions, e.g.: /boot + / + [cryptSWAP] + /home
                # Setup encryption
                # Open encryption
                # Format partitions
                # Close encryption
                echo "Wipe old partition headers ..." && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=1 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=500 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=20500 count=${MiB_initial_wipe} && \
                dd if=/dev/zero of=$DISK_SYSTEM bs=1MiB seek=22500 count=${MiB_initial_wipe} && \
                echo "Write MSDOS partition table ..." && \
                parted -s $DISK_SYSTEM -- mklabel msdos && \
                echo "Create partitions ..." && \
                parted -s $DISK_SYSTEM -- mkpart primary 1MiB 500MiB mkpart primary 500MiB 20500MiB mkpart primary 20500MiB 22500MiB mkpart primary 22500MiB -1s && \
                echo "Create LUKS header ..." && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}1 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}2 && \
                cryptsetup -v --iter-time 500 --use-random --type luks1 luksFormat ${DISK_SYSTEM}4 && \
                echo "Open encryption ..." && \
                cryptsetup luksOpen ${DISK_SYSTEM}1 "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}2 "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                cryptsetup luksOpen ${DISK_SYSTEM}4 "${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" && \
                echo "Create filesystems ..." && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                mkfs.ext4 /dev/mapper/"${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" && \
                echo "Store disk passphrases at a save place." && \
                sleep $PROCESS_DELAY && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}1${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}2${CRYPT_SUFFIX}" && \
                cryptsetup luksClose "${DISK_SYSTEM##*/}4${CRYPT_SUFFIX}" || \
                  catch_error

                # Hit key
                echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
                hitenter || abort
            esac
            ;;
          11)
            # Add space on screen
            echo; echo;
            echo "Starting job \`${menulist_operation[$((feedback*2-1))]}' ..."
            sleep $PROCESS_DELAY

            open_encryption
            assign_mountpoints

            # Hit key
            echo "... done with job \`${menulist_operation[$((feedback*2-1))]}'"
            hitenter || abort
            ;;
        esac
        ;;
      3)    # extra button
        [ -n "$FLAG_ROOT" ] && {
          echo; echo;
          break
        }
        ;;
      *)
        echo; echo;
        abort
        ;;
    esac
  done
}

set_system_wallpaper() {

  # Precondition: Folder /mnt must refer to a mounted partition.

  # Copy desktop's background
  #   Note this image is specific to OpenRC
  cp -a /etc/wallpaper.png /mnt/etc/wallpaper.png
}

set_system_config() {

  # positional parameter
  local -r desktop_environment="${1^^}"   # e.g.: LXDE, XFCE, MATE

  # locals
  local -r xkbmap="$(setxkbmap -query)"
  local -r xkbmap_rules=$(echo "${xkbmap}" | $SED -r -e '/rules/!d;s/^.*[ \t]//;' -)
  local -r xkbmap_model=$(echo "${xkbmap}" | $SED -r -e '/model/!d;s/^.*[ \t]//;' -)
  local -r xkbmap_layout=$(echo "${xkbmap}" | $SED -r -e '/layout/!d;s/^.*[ \t]//;' -)

  # Copy live system’s skel folder into the new system
  cp -a /etc/skel/ /mnt/etc/

  # Adjust /mnt/etc/sudoers
  $SED -r -i \
    -e '/^# %wheel ALL=\(ALL\) ALL/s/^# //;' \
      /mnt/etc/sudoers

  # Set up default .xinitrc
  echo "setxkbmap -rules ${xkbmap_rules} -model ${xkbmap_model} -layout ${xkbmap_layout}" > /mnt/etc/skel/.xinitrc
  case "${desktop_environment}" in
    'LXDE')
      echo "exec startlxde      " >> /mnt/etc/skel/.xinitrc
      ;;
    'XFCE')
      echo "exec startxfce4     " >> /mnt/etc/skel/.xinitrc
      ;;
    'MATE')
      echo "exec mate-session   " >> /mnt/etc/skel/.xinitrc
      ;;
  esac
  chmod +x /mnt/etc/skel/.xinitrc

  # Adjust default .bash_profile to start X automatically
  echo "startx" >> /mnt/etc/skel/.bash_profile
}

check_dbus_user() {

  # Precondition: Folder /mnt must refer to a mounted partition.

  # locals
  local tmpfile=/mnt/checkDBUS.sh

  # Create the dbus user if it doesn't exist
  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v grep)\" ] && notool 'grep'                           " >> "$tmpfile"
  echo "[ -z \"\$(command -v groupadd)\" ] && notool 'groupadd'                   " >> "$tmpfile"
  echo "[ -z \"\$(command -v useradd)\" ] && notool 'useradd'                     " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "[ \$(grep dbus /etc/group) = \"\" ] &&                                  \\" >> "$tmpfile"
  echo "  groupadd -g 81 dbus                                                     " >> "$tmpfile"
  echo "[ \$(grep dbus /etc/passwd) = \"\" ] &&                                 \\" >> "$tmpfile"
  echo "  useradd -r -s /sbin/nologin -g 81 -u 81 dbus                            " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# cancel error status                                                     " >> "$tmpfile"
  echo "true                                                                      " >> "$tmpfile"
  chroot_exec "$tmpfile" || catch_error
}

enable_services_OpenRC() {

  # Precondition: Folder /mnt must refer to a mounted partition.

  # locals
  local tmpfile=/mnt/servicesOpenRC.sh

  # Enable services with OpenRC
  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v rc-update)\" ] && notool 'rc-update'                 " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "rc-update add NetworkManager default                                      " >> "$tmpfile"
  echo "rc-update add dbus default                                                " >> "$tmpfile"
  echo "rc-update add alsasound default                                           " >> "$tmpfile"
  chroot_exec "$tmpfile" || catch_error
}

enable_services_SystemD() {

  # Precondition: Folder /mnt must refer to a mounted partition.

  # locals
  local tmpfile=/mnt/servicesSystemD.sh

  # Enable services with OpenRC
  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v systemctl)\" ] && notool 'systemctl'                 " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "systemctl enable NetworkManager                                           " >> "$tmpfile"

  # DBus is not meant to be started with SystemD?
  #echo "systemctl enable dbus               " >> "$tmpfile"

  # How to enable ALSA Services with SystemD?
  # See: https://wiki.archlinux.org/title/Advanced_Linux_Sound_Architecture#ALSA_and_systemd
  #echo "systemctl enable alsasound          " >> "$tmpfile"

  chroot_exec "$tmpfile" || catch_error
}

chroot_exec() {

  # Precondition: Folder /mnt must refer to a mounted partition.

  # positional parameter
  local -r scriptfile="$1"

  # locals
  local errstat

  chmod u+x "${scriptfile}"
  arch-chroot /mnt "/${scriptfile##*/}"
  errstat=$?
  rm -f "${scriptfile}"

  return $errstat
}

set_password() {

  # positional parameter
  local -r algo="$1"
  local -r user="$2"
  local -r priviledged="$3"

  # locals
  local -r tmpfile="/mnt/setPassword.sh"
  local feedback1
  local feedback2

  while [ true ]; do
    feedback1=$( \
      $DIALOG ${FLAGS_DIALOG[@]} \
        --cancel-label "Disable" \
        --quoted --passwordbox "Enter Password for User \`${user}'" ${WIDGET_DIM} \
    )
    case $? in
      0)
        feedback2=$( \
          $DIALOG ${FLAGS_DIALOG[@]} \
            --quoted --passwordbox "Repeat Password for User \`${user}'" ${WIDGET_DIM} \
        )
        case $? in
          0)
            if [ -z "${feedback1}" -o "${feedback1}" != "${feedback2}" ]; then
              $DIALOG ${FLAGS_DIALOG[@]} \
                --msgbox "Password not valid, try again!" ${WIDGET_DIM}
            else
              echo; echo;
              echo "#!/bin/bash                                                               " >  "$tmpfile"
              echo "                                                                          " >> "$tmpfile"
              echo "notool() {                                                                " >> "$tmpfile"
              echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
              echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
              echo "  exit 1                                                                  " >> "$tmpfile"
              echo "}                                                                         " >> "$tmpfile"
              echo "                                                                          " >> "$tmpfile"
              echo "# tool check                                                              " >> "$tmpfile"
              echo "[ -z \"\$(command -v usermod)\" ] && notool 'usermod'                     " >> "$tmpfile"
              echo "                                                                          " >> "$tmpfile"
              echo "usermod                                                                 \\" >> "$tmpfile"
              echo "  -p \$(openssl passwd ${algo} \"${feedback1}\")                        \\" >> "$tmpfile"
              echo "    ${user}                                                               " >> "$tmpfile"
              chroot_exec "$tmpfile" || abort
              [ "$user" == "$user_root" -o -n "$priviledged" ] && FLAG_ADMIN='on'
              break
            fi
            ;;
          *)
            $DIALOG ${FLAGS_DIALOG[@]} \
              --msgbox "Try again!" ${WIDGET_DIM}
            ;;
        esac
        ;;
      *)
        $DIALOG ${FLAGS_DIALOG[@]} \
          --msgbox "Password disabled." ${WIDGET_DIM}
        echo; echo;
        break
        ;;
    esac
  done
}

add_user_account() {

  # positional parameter
  local -r algo="$1"

  # locals
  local feedback
  local tmpfile=/mnt/newUserAccount.sh
  local priviledged=''
  local -a list_of_new_users=()

  while [ true ]; do
    $DIALOG ${FLAGS_DIALOG[@]} \
      --extra-button \
      --extra-label "Standard" \
      --ok-label "Priviledged" \
      --cancel-label "No" \
      --yesno "Current List of New Users:\n\`${list_of_new_users[*]}'\n\nCreate a new User Account?" ${WIDGET_DIM}
    case $? in
      0)
        priviledged='on'
        ;&
      3)
        feedback=$(\
          $DIALOG ${FLAGS_DIALOG[@]} \
            --inputbox "Enter Username\nAllowed characters are: lower case letters, numbers, underscore, hyphen, a final dolar sign" ${WIDGET_DIM} \
        )
        case $? in
          0)
            echo; echo;
            if [  -z "${feedback}" -o \
                  -n "`echo ${feedback} | $SED -r -e '/.{33,}/!d;' -`" -o \
                  -n "`echo ${feedback} | $SED -r -e '/^[a-z_][0-9a-z_-]*[$]?$/d;' -`" \
            ]; then
              $DIALOG ${FLAGS_DIALOG[@]} \
                --msgbox "Not a valid username!" ${WIDGET_DIM}
            else
              ( \
                echo "#!/bin/bash                                                               " >  "$tmpfile"
                echo "                                                                          " >> "$tmpfile"
                echo "notool() {                                                                " >> "$tmpfile"
                echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
                echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
                echo "  exit 1                                                                  " >> "$tmpfile"
                echo "}                                                                         " >> "$tmpfile"
                echo "                                                                          " >> "$tmpfile"
                echo "# tool check                                                              " >> "$tmpfile"
                echo "[ -z \"\$(command -v useradd)\" ] && notool 'useradd'                     " >> "$tmpfile"
                echo "                                                                          " >> "$tmpfile"
                echo "useradd                                                                 \\" >> "$tmpfile"
                echo "  --comment ${feedback^}                                                \\" >> "$tmpfile"
                echo "  --create-home                                                         \\" >> "$tmpfile"
                echo "  --no-user-group                                                       \\" >> "$tmpfile"
                echo "  --gid 984                                                             \\" >> "$tmpfile"
                echo "  ${priviledged:+--groups wheel}                                        \\" >> "$tmpfile"
                echo "    ${feedback};                                                          " >> "$tmpfile"
              ) && \
              chroot_exec "$tmpfile" && \
              list_of_new_users+=("${feedback}") && \
              $DIALOG ${FLAGS_DIALOG[@]} \
                --msgbox "User \`${feedback}'${priviledged:+, priviledged,} successfully created." ${WIDGET_DIM} && \
              set_password "${openssl_passwd_algo}" "${feedback}" "${priviledged}" || \
                catch_error
            fi
            priviledged=''
            ;;
          *)
            ;;
        esac
        ;;
      *)
        [ -n "$FLAG_ADMIN" ] && {
          echo; echo;
          break
        }
        $DIALOG ${FLAGS_DIALOG[@]} \
          --msgbox "At least one new, priviledged user must be set up." ${WIDGET_DIM}
        ;;
    esac
  done
}

set_hostname_OpenRC() {

  # positional parameter
  local -r new_hostname="$1"

  # edit /etc/conf.d/hostname
  $SED -r -i \
    -e "s|localhost|${new_hostname}|;" \
      /mnt/etc/conf.d/hostname;

  # delete SystemD configuration files (!)
  rm -f /mnt/etc/hostname
  rm -f /mnt/etc/hosts
}

set_hostname_SystemD() {

  # positional parameter
  local -r new_hostname="$1"

  # edit /etc/hostname
  echo "${new_hostname}" > /mnt/etc/hostname

  # edit /etc/hosts
  sed -r -i \
    -e '/^127\.0\.0\.1/d;' \
    -e '/^\:\:1      /d;' \
      /mnt/etc/hosts
  echo "127.0.0.1 localhost.localdomain localhost ${new_hostname}" >> /mnt/etc/hosts
  echo "::1       localhost.localdomain localhost ${new_hostname}" >> /mnt/etc/hosts

  # delete OpenRC configuration files (!)
  rm -f /mnt/etc/conf.d/hostname
}

set_localtime() {

  # positional parameter
  local -r new_timezone="$1"

  ln \
    -sf \
      /mnt/usr/share/zoneinfo/"${new_timezone}" /mnt/etc/localtime
}

install_packages() {

  # positional parameter
  local -r set_of_packages="$1"

  # locals
  local tmpfile=/mnt/installPackages.sh

  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v pacman)\" ] && notool 'pacman'                       " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "pacman -S ${set_of_packages}                                            \\" >> "$tmpfile"
  echo "  --confirm                                                               " >> "$tmpfile"
  chroot_exec "$tmpfile" || catch_error
}

make_initramfs() {

  # locals
  local tmpfile=/mnt/makeInitramfs.sh

  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v mkinitcpio)\" ] && notool 'mkinitcpio'               " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "mkinitcpio                                                              \\" >> "$tmpfile"
  echo "  -p linux-libre                                                          " >> "$tmpfile"
  chroot_exec "$tmpfile" || abort
}

gen_locales() {

  # positional parameter
  local -r -a default_locales=("$@")

  # locals
  local aux
  local i
  local -a checklist_locale=()
  local feedback
  local -a record=()
  local cfgfile=/mnt/etc/locale.gen
  local tmpfile=/mnt/genLocales.sh
  local bakfile="${cfgfile}.bak"

  cp "$cfgfile" "$bakfile"

  for i in $($SED -r -e '/^#[ ]|^#$/d;s/^#//;s/[ \t]*$//;s/ /#/g;' $cfgfile); do
    checklist_locale+=("${i//\#/ }" "${i//\#/ }" "off")
  done

  feedback=$( \
    $DIALOG ${FLAGS_DIALOG[@]} \
      --cancel-label "Abort" \
      --checklist \
        "Select Locales\nDefaulting to: \`${default_locales[*]/%/ }'" \
        ${MENUWIDGET_DIM} \
        "${checklist_locale[@]}" \
  )
  case $? in
    0)
      if [ -z "$feedback" ]; then
        $DIALOG ${FLAGS_DIALOG[@]} \
          --msgbox "Locales defaulting to: \`${default_locales[*]/%/ }'" ${WIDGET_DIM}
        record=("${default_locales[@]}")
      else
        record=("${feedback}")
      fi
      echo; echo;
      ;;
    *)
      echo; echo;
      abort
      ;;
  esac

  for i in "${record[@]}"; do
    $SED -r -i \
      -e "/^.$i/s/^#//;" \
        "$cfgfile"
  done

  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v locale-gen)\" ] && notool 'locale-gen'               " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "locale-gen                                                                " >> "$tmpfile"
  chroot_exec "$tmpfile" || abort
}

set_language() {

  # positional parameter
  local -r default_language="$1"

  # locals
  local tmpfile=/mnt/setLanguage.sh

  echo "#!/bin/bash                                                               " >  "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "notool() {                                                                " >> "$tmpfile"
  echo "  local -r tool=\"\$1\"                                                   " >> "$tmpfile"
  echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> "$tmpfile"
  echo "  exit 1                                                                  " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# tool check                                                              " >> "$tmpfile"
  echo "[ -z \"\$(command -v locale)\" ] && notool 'locale'                       " >> "$tmpfile"
  echo "[ -z \"\$(command -v dialog)\" ] && notool 'dialog'                       " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "declare i                                                                 " >> "$tmpfile"
  echo "declare -a radiolist_language=()                                          " >> "$tmpfile"
  echo "declare feedback                                                          " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# collect available languages                                             " >> "$tmpfile"
  echo "for i in \$(locale --all-locales); do                                     " >> "$tmpfile"
  echo "  radiolist_language+=(\"\$i\" \"\$i\" \"off\")                           " >> "$tmpfile"
  echo "done                                                                      " >> "$tmpfile"
  echo "                                                                          " >> "$tmpfile"
  echo "# set language                                                            " >> "$tmpfile"
  echo "feedback=\$(                                                            \\" >> "$tmpfile"
  echo "  dialog ${FLAGS_DIALOG[@]}                                             \\" >> "$tmpfile"
  echo "    --radiolist                                                         \\" >> "$tmpfile"
  echo "      \"Select your Language\\nDefaulting to: $default_language\"       \\" >> "$tmpfile"
  echo "      ${MENUWIDGET_DIM}                                                 \\" >> "$tmpfile"
  echo "      \${radiolist_language[@]};                                        \\" >> "$tmpfile"
  echo ")                                                                         " >> "$tmpfile"
  echo "[ \$? -ne 0 -o -z \"\$feedback\" ] && {                                   " >> "$tmpfile"
  echo "  dialog ${FLAGS_DIALOG[@]}                                             \\" >> "$tmpfile"
  echo "    --msgbox \"Language defaulting to: $default_language\" ${WIDGET_DIM}  " >> "$tmpfile"
  echo "  feedback=\"$default_language\"                                          " >> "$tmpfile"
  echo "}                                                                         " >> "$tmpfile"
  echo "echo \"LANG=\$feedback\" > /etc/locale.conf                               " >> "$tmpfile"
  chroot_exec "$tmpfile" || abort
}

dismount_mountpoints() {

  # dismount
  umount \
    -R /mnt \
      &> /dev/null
  swapoff \
    -a \
      &> /dev/null

  # reset records
  mountpoints_assigned=()
  partitions_processed=()

  # clear flags
  FLAG_USR=''
  FLAG_LVM2=''
  FLAG_ROOT=''
  FLAG_CRYPT=''
  FLAG_PLAIN='on'

  # Wait for Update
  udevadm settle
}

close_encryption() {

  # positional parameter

  # locals
  local -r -a type_crypt=( \
    $( \
      lsblk -n -oPATH,TYPE | \
      egrep ${DISK_SYSTEM##*/} | \
      egrep crypt | \
      cut -f1 -d' ' - \
    ) \
  )
  local n

  for n in "${type_crypt[@]}"; do
    cryptsetup luksClose "${n}"
  done
}

catch_error() {

  # positional parameter

  echo "Oops, an error occured. Proceed anyway?"
  hitenter || abort
}

abort() {

  # positional parameter

  echo "Aborting ..."
  echo "Mountpoints are NOT dismounted."
  echo "Encryption is NOT closed."
  exit 1
}

get_device() {

  # positional parameter
  local -r mountpoint="$1"
  local -n parray1="$2"
  local -n parray2="$3"
  local -n presult="$4"

  # locals
  local i
  local -i n=0

  for i in "${parray1[@]}"; do
    [ "$i" == "$mountpoint" ] && {
      presult="${parray2[$n]##*\/}"
      return 0
    }
    n+=1
  done
  return 1
}

main() {

  # positional parameter

  # script wide variables
  declare -r WIDGET_DIM='-1 -1'
  declare -r MENUWIDGET_DIM='-1 -1 -1'
  declare -r PROCESS_DELAY=3
  declare -r CRYPT_SUFFIX='_crypt'
  declare DISK_SYSTEM=''
  declare FLAG_INTELGPU='on'
  declare FLAG_NVIDIAGPU=''
  declare FLAG_DISK=''
  declare FLAG_ROOT=''
  declare FLAG_USR=''
  declare FLAG_LVM2=''
  declare FLAG_CRYPT=''
  declare FLAG_PLAIN='on'
  declare FLAG_ADMIN=''
  declare -a partitions_processed=()
  declare -a mountpoints_assigned=()
  declare -r openssl_passwd_algo='-6'   # see `openssl passwd -help`
  declare -r config_pacman_keyserver='hkp://keys.gnupg.net'
  declare -r user_root='root'
  declare -r MiB_initial_wipe=25

  # default settings, customizable
  local -r   default_consolefont="eurlatgr"
  local -r default_consolekeymap="de"
  local -r -a    default_locales=( \
    "en_US.UTF-8 UTF-8" \
    "en_GB.UTF-8 UTF-8" \
    "es_ES.UTF-8 UTF-8" \
    "it_IT.UTF-8 UTF-8" \
    "fr_FR.UTF-8 UTF-8" \
    "pt_PT.UTF-8 UTF-8" \
    "pl_PL.UTF-8 UTF-8" \
    "de_DE.UTF-8 UTF-8" \
  )
  local -r      default_language="de_DE.utf8"
  local -r      default_timezone="Europe/Berlin"
  local -r      default_hostname="zerocat-parabola-machine"

  # local constants
  local -r           config_pacman="/etc/pacman.conf"
  local -r config_pacman_alternate="/etc/alt-pacman.conf"
  local -r       config_pacman_gpg="/etc/pacman.d/gnupg/gpg.conf"
  local -r       config_mkinitcpio="/mnt/etc/mkinitcpio.conf"
  local -r -a checklist_mkinitcpio=(
    1 "Write Configuration File"                      on
    2 "Refine Configuration File with GNU Nano"       off
    3 "Generate Initial Ramdisk"                      on
  )
  local -r -a menulist_mountpoint=(
    1 "/mnt/"
    2 "/mnt/boot"
    3 "/mnt/usr"
    4 "/mnt/usr/local"
    5 "/mnt/var"
    6 "/mnt/tmp"
    7 "/mnt/home"
    8 "[SWAP]"
    9 "[cryptSWAP]"   # specific to SystemD
  )
  local -r -a checklist_tweak=(
    1   "Key Strengthening"                                     on
    2   "Restrict Access to important Directories"              on
    3   "Lockout User after three failed Login Attempts"        off
  )
  local -r -a radiolist_DE=(
    1   "LXDE"      on
    2   "XFCE"      off
    3   "MATE"      off
  )
  local -r -a checklist_main=(
    1   "Live System: Disable nonsystemd Repository"                  on
    2   "Live System: Update Package Database"                        on
    3   "Live System: Select Drive, mount Partitions"                 on
    4   "Install GNU System with User \`$user_root'"                  on
    5   "Configure GNU System, set Password for User \`$user_root'"   on
    6   "Apply extra Security Tweaks ..."                             on
    7   "Install Desktop Environment ..."                             on
    8   "Install Desktop Applications"                                on
    9   "Create User Accounts"                                        on
    10  "Install Kernel with default Initial Ramdisk Image"           on
    11  "Configure Kernel Console"                                    on
    12  "Reconfigure & Remake Initial Ramdisk Image ..."              on
    13  "GRUB Bootloader Options ..."                                 on
    14  "Live System: Dismount Partitions, close Encryption"          on
  )
  local -r -a packages_Base_OpenRC=(
    "base-openrc"
    "grep"
  )
  local -r -a packages_Base_SystemD=(
    "base"
  )
  local -r -a packages_Base_Common=(
    "sudo"
    "nano"
    "dialog"
    "man-db"
    "pcurses"
    "gvfs-mtp"
    "gphoto2"
    "pulseaudio-alsa"
    "alsa-utils"
  )
  local -r -a packages_Kernel=(
    "linux-libre"
  )
  local -r -a packages_GRUB=(
    "grub"
  )
  local -r -a packages_X=(
    "xorg-server"
    "xf86-input-evdev"
    "xf86-input-synaptics"
    "xf86-video-ati"
    "xf86-video-dummy"
    "xf86-video-fbdev"
    "xf86-video-intel"
    "xf86-video-nouveau"
    "xf86-video-openchrome"
    "xf86-video-sisusb"
    "xf86-video-vesa"
    "xf86-video-vmware"
    "xf86-video-voodoo"
    "xf86-video-qxl"
    "xorg-xinit"
    "xlockmore"
    "xterm"
  )
  # LXDE: xscreensaver has unresolved dependencies?
  # LXDE: xterm is required to launch alsamixer from panel icon
  local -r -a packages_LXDE=(
    "lxde"
    "leafpad"
    "xarchiver"
    "xscreensaver"
    "gnome-screenshot"
    "galculator-gtk2"
    "epdfview"
  )
  local -r -a packages_XFCE=(
    "xfce4"
    "xfce4-goodies"
    "pavucontrol"
    "galculator-gtk2"
    "epdfview"
  )
  local -r -a packages_MATE=(
    "mate"
    "mate-extra"
  )
  local -r -a packages_DE_Common=(
    "network-manager-applet"
    "xdg-user-dirs"
  )
  local -r -a packages_OpenRC=(
    "openrc-desktop"
    "polkit-elogind"
    "networkmanager-elogind"
  )
  local -r -a packages_SystemD=(
    "polkit"
    "networkmanager"
  )
  local -r -a packages_User=(
    "gparted"
    "abiword"
    "smplayer"
    "gnumeric"
    "iceweasel"
    "claws-mail"
    "jami-gnome"
  )

  # locals
  local init_modules='i915 nouveau '
  local hooks_standard='base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck usr shutdown '
  local hooks_systemd='base systemd autodetect keyboard sd-vconsole modconf block sd-encrypt lvm2 filesystems fsck usr sd-shutdown '
  local init_system
  local option
  local feedback
  local feedback2
  local swapvol
  local cryptdev
  local uuid
  local i
  local x
  local -i n
  local -a radiolist_timezone=()
  local -a radiolist_consolefont=()
  local -a radiolist_consolekeymaps=()
  local -a checklist_grub=()
  local -a radiolist_GRUB=()

  # welcome
  welcome

  # reset init system
  cp "$config_pacman" "$config_pacman_alternate";
  init_system="openrc"

  # start main checklist
  option=$( \
    $DIALOG ${FLAGS_DIALOG[@]} \
      --cancel-label "Abort" \
      --checklist \
        "Parabola Installation Checklist" \
        ${MENUWIDGET_DIM} \
        "${checklist_main[@]}"; \
  )
  case $? in
    0)
      echo; echo;
      [ -n "$option" ] && {
        # process main checklist
        echo "Process Main Checklist ..."
        sleep $PROCESS_DELAY
        echo
        for i in $option; do
          echo "Starting job $i: “${checklist_main[$((i*3-2))]}” ..."
          sleep $PROCESS_DELAY
          case $i in
            1)    # Live System: disable nonsystemd repository
              # Edit /etc/pacman.conf such that repository nonsystemd is disabled:
              $SED -r \
                -e '/^\[nonsystemd\]/,+1s/^/#/;' \
                  "$config_pacman" > "$config_pacman_alternate";
              init_system="systemd"
              ;;
            2)    # Live System: update package database
              sync_keyrings || abort
              ;;
            3)    # Live System: select drive, format, mount partitions
              set_DISK_SYSTEM
              dismount_mountpoints
              close_encryption
              disk_operations
              ;;
            4)    # install GNU system with user root
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # Install base system
                case "$init_system" in
                  'openrc')
                    pacstrap \
                      -C "$config_pacman_alternate" \
                        /mnt ${packages_Base_OpenRC[@]} || \
                          catch_error
                    ;;
                  'systemd')
                    pacstrap \
                      -C "$config_pacman_alternate" \
                        /mnt ${packages_Base_SystemD[@]} || \
                          catch_error
                    ;;
                esac
                install_packages "${packages_Base_Common[*]}"
              }
              ;;
            5)    # configure GNU system, set password for user root
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {

                # generate crypttab (SystemD)
                [ "${init_system,,}" == 'systemd' -a -n "$FLAG_CRYPT" ] && {
                  n=0; uuid='';
                  while [ ${n} -lt ${#partitions_processed[@]} ]; do
                    x="${partitions_processed[$n]##*/}"
                    case "${mountpoints_assigned[$n]}" in
                      '/')
                        ;;
                      '[SWAP]')
                        ;;
                      '[cryptSWAP]')
                        echo "${x%${CRYPT_SUFFIX}}${CRYPT_SUFFIX} /dev/${x%${CRYPT_SUFFIX}} /dev/urandom swap" >> /mnt/etc/crypttab
                        ;;
                      *)
                        uuid="UUID=$( \
                          lsblk -n -oUUID,PATH | \
                          egrep /dev/${x%${CRYPT_SUFFIX}} | \
                          cut -f1 -d' ' - \
                        )"
                        echo "${x} ${uuid}" >> /mnt/etc/crypttab
                        ;;
                    esac
                    n+=1
                  done
                }

                # generate fstab, set swapvol variable for GRUB
                genfstab \
                  -U \
                  -p /mnt \
                    >> /mnt/etc/fstab
                n=0; uuid=''; swapvol='';
                while [ ${n} -lt ${#partitions_processed[@]} ]; do
                  x="${partitions_processed[$n]##*/}"
                  case "${mountpoints_assigned[$n]}" in
                    '[SWAP]')
                      x="/dev/${x%${CRYPT_SUFFIX}}"
                      swapvol="${x}"
                      ;;
                    '[cryptSWAP]')
                      if [ "${init_system,,}" == 'systemd' -a -n "$FLAG_CRYPT" ]; then
                        x="/dev/mapper/${x%${CRYPT_SUFFIX}}${CRYPT_SUFFIX}"
                        echo "# ${x}" >> /mnt/etc/fstab
                        echo "${uuid:-${x}} none swap defaults 0 0" >> /mnt/etc/fstab
                        echo >> /mnt/etc/fstab
                      fi
                      ;;
                  esac
                  n+=1
                done

                # set hostname
                while [ true ]; do
                  feedback=$( \
                    $DIALOG ${FLAGS_DIALOG[@]} \
                      --cancel-label "Abort" \
                      --inputbox \
                        "Enter Hostname" \
                        ${WIDGET_DIM} \
                        "$default_hostname"
                  )
                  case $? in
                    0)
                      if [  -z "$feedback" -o \
                            -n "`echo $feedback | $SED -r -e '/.{254,}/!d;' -`" -o \
                            -n "`echo $feedback | $SED -r -e '/^[.-]|[.][-]|[-][.]|[.-]$|[^a-zA-Z0-9.-]/!d;' -`" \
                      ]; then
                        $DIALOG ${FLAGS_DIALOG[@]} \
                          --msgbox "Not a valid hostname!" ${WIDGET_DIM}
                      else
                        if [ "$init_system" == 'openrc' ]; then
                          set_hostname_OpenRC "$feedback"
                        else
                          set_hostname_SystemD "$feedback"
                        fi
                        break 1
                      fi
                      ;;
                    *)
                      echo; echo;
                      abort
                      ;;
                  esac
                done

                # collect available timezones
                radiolist_timezone=( \
                  $( \
                    find /mnt/usr/share/ -wholename '*zoneinfo/[^posixright/]*/[^/]*' -print | \
                    sed -r -e 's/(^.*\/)(.*\/)(.*)/\2\3 \3 off/;' - | \
                    sort - \
                  ) \
                )

                # set local time
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --radiolist \
                      "Select your Timezone\nDefaulting to: $default_timezone" \
                      ${MENUWIDGET_DIM}  \
                      "${radiolist_timezone[@]}" \
                )
                case $? in
                  0)
                    [ -z "$feedback" ] && {
                      $DIALOG ${FLAGS_DIALOG[@]} \
                        --msgbox "Timezone defaulting to: \`$default_timezone'" ${WIDGET_DIM}
                      feedback="$default_timezone"
                    }
                    set_localtime "$feedback"
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac

                # set hardware clock type
                echo "#!/bin/bash               " > /mnt/setHWClock.sh
                echo "hwclock --systohc --utc   " >> /mnt/setHWClock.sh
                chroot_exec "/mnt/setHWClock.sh" || catch_error

                # select locales and generate
                gen_locales "${default_locales[@]}"

                # select and set language
                set_language "$default_language"

                # set password for user root
                set_password "$openssl_passwd_algo" "$user_root"
              }
              ;;
            6)    # apply extra security tweaks
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --checklist "Select Security Tweaks" ${MENUWIDGET_DIM} "${checklist_tweak[@]}"
                )
                case $? in
                  0)
                    echo; echo;
                    [ -n "$feedback" ] && {
                      echo "Process Security Tweak checklist ..."
                      sleep $PROCESS_DELAY
                      echo
                      for x in $feedback; do
                        echo "Starting job $x: “${checklist_tweak[$((x*3-2))]}” ...";
                        sleep $PROCESS_DELAY
                        case $x in
                          1)    # key strengthening
                            $SED -r -i \
                              -e '/^password/s/$/ rounds=65536/;' \
                                /etc/pam.d/passwd
                            ;;
                          2)    # restrict access
                            chmod 700 \
                              /boot \
                              /etc/{iptables,arptables} \
                                &> /dev/null
                            ;;
                          3)    # lockout 10min
                            $SED -r -i \
                              -e '/^auth.*required.*pam\_tally.so/s/(^.*)(onerr=succeed.*$)/\1 deny=2 unlock\_time=600 \2/;' \
                                /etc/pam.d/system-login
                            ;;
                        esac
                        echo "... done with job $x: “${checklist_tweak[$((x*3-2))]}”"
                        hitenter || abort
                      done
                      echo "... Security Tweak Checklist processed."
                      hitenter || abort
                    }
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac
              }
              ;;
            7)    # install Desktop Environment
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # install common packages
                install_packages "${packages_X[*]}"
                install_packages "${packages_DE_Common[*]}"
                if [ "$init_system" == 'openrc' ]; then
                  install_packages "${packages_OpenRC[*]}"
                else
                  install_packages "${packages_SystemD[*]}"
                fi

                # retrieve user input
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --radiolist "Select your Desktop Environment" ${MENUWIDGET_DIM} "${radiolist_DE[@]}"
                )
                case $? in
                  0)
                    echo; echo;
                    case $feedback in
                      1)
                        # install packages
                        install_packages "${packages_LXDE[*]}"

                        # setup configuration files to get X started
                        [ "$init_system" == 'openrc' ] && \
                          set_system_wallpaper
                        set_system_config "LXDE"
                        ;;
                      2)
                        # install packages
                        install_packages "${packages_XFCE[*]}"

                        # setup configuration files to get X started
                        set_system_config "XFCE"
                        ;;
                      3)
                        # install packages
                        install_packages "${packages_MATE[*]}"

                        # setup configuration files to get X started
                        set_system_config "MATE"
                        ;;
                    esac

                    # check for existing dbus user
                    check_dbus_user

                    # enable services
                    if [ "$init_system" == 'openrc' ]; then
                      enable_services_OpenRC
                    else
                      enable_services_SystemD
                    fi
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac
              }
              ;;
            8)    # install extra User Applications
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # Install packages
                install_packages "${packages_User[*]}"
              }
              ;;
            9)    # create user accounts
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # Add new users
                add_user_account "$openssl_passwd_algo"
              }
              ;;
            10)   # install kernel with default initial ramdisk image
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # Install kernel
                install_packages "${packages_Kernel[*]}"
              }
              ;;
            11)   # configure kernel console
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                # collect available console fonts
                radiolist_consolefont=( \
                  $( \
                    find /mnt/usr/share/kbd/consolefonts -name '*.psf*.gz' -print | \
                    sed -r -e 's/(^.*\/)(.*)(\..*)(\..*$)/\2 \2 off/;' - | \
                    sort - \
                  ) \
                )

                # set console font
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --radiolist \
                      "Pick your Font for the Kernel Console\nDefaulting to: $default_consolefont" \
                      ${MENUWIDGET_DIM} \
                      "${radiolist_consolefont[@]:-${default_consolefont} ${default_consolefont} on}" \
                )
                case $? in
                  0)
                    [ -z "$feedback" ] && {
                      $DIALOG ${FLAGS_DIALOG[@]} \
                        --msgbox "Console font defaulting to: \`$default_consolefont'" ${WIDGET_DIM}
                      feedback="$default_consolefont"
                    }
                    echo "FONT=\"$feedback\"" > "/mnt/etc/vconsole.conf"
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac

                # collect available console keymaps
                radiolist_consolekeymaps=( \
                  $( \
                    find /mnt/usr/share/kbd/keymaps -name '*.map.gz' -print | \
                    sed -r -e 's/(^.*\/)(.*)(\.map\.gz)/\2 \2 off/;' - | \
                    sort - \
                  ) \
                )

                # set console keymap
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --radiolist \
                      "Pick your Keymap for the Kernel Console\nDefaulting to: $default_consolekeymap" \
                      ${MENUWIDGET_DIM} \
                      "${radiolist_consolekeymaps[@]:-${default_consolekeymap} ${default_consolekeymap} on}" \
                )
                case $? in
                  0)
                    [ -z "$feedback" ] && {
                      $DIALOG ${FLAGS_DIALOG[@]} \
                        --msgbox "Console keymap defaulting to: \`$default_consolekeymap'" ${WIDGET_DIM}
                      feedback="$default_consolekeymap"
                    }
                    echo "KEYMAP=\"$feedback\"" >> "/mnt/etc/vconsole.conf"
                    echo; echo;
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac
              }
              ;;
            12)   # reconfigure and remake initial ramdisk image
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --checklist "Mkinitcpio Configuration Options" ${MENUWIDGET_DIM} "${checklist_mkinitcpio[@]}" \
                )
                case $? in
                  0)
                    echo; echo;
                    [ -n "$feedback" ] && {
                      echo "Process Mkinitcpio Configuration Checklist ..."
                      sleep $PROCESS_DELAY
                      echo
                      for x in $feedback; do
                        echo "Starting job $x: “${checklist_mkinitcpio[$((x*3-2))]}” ...";
                        sleep $PROCESS_DELAY
                        case $x in
                          1)
                            [ -z "$FLAG_INTELGPU" ] && {
                              init_modules="${init_modules/i915 /}"
                            }
                            [ -z "$FLAG_NVIDEAGPU" ] && {
                              init_modules="${init_modules/nouveau /}"
                            }
                            sed -r -i \
                              -e "/^MODULES=/s/^/#/;" \
                              -e "/^# BINARIES$/i# Modules suggested by install script – select and refine as required\n# standard:\nMODULES=(${init_modules})\n" \
                                "$config_mkinitcpio"
                            [ -z "$FLAG_USR" ] && {
                              hooks_standard="${hooks_standard/usr /}"
                              hooks_systemd="${hooks_systemd/usr /}"
                            }
                            [ -z "$FLAG_LVM2" ] && {
                              hooks_standard="${hooks_standard/lvm2 /}"
                              hooks_systemd="${hooks_systemd/lvm2 /}"
                            }
                            [ -z "$FLAG_CRYPT" ] && {
                              hooks_standard="${hooks_standard/encrypt /}"
                              hooks_systemd="${hooks_systemd/sd-encrypt /}"
                            }
                            [ -z "$FLAG_CRYPT" -a -z "FLAG_USR" ] && {
                              hooks_standard="${hooks_standard/shutdown /}"
                              hooks_systemd="${hooks_systemd/sd-shutdown /}"
                            }
                            sed -r -i \
                              -e "/^HOOKS=/s/^/#/;" \
                              -e "/^# COMPRESSION$/i# Hooks suggested by install script – select and refine as required\n# standard:\nHOOKS=(${hooks_standard})\n# systemd:\n#HOOKS=(${hooks_systemd})\n" \
                                "$config_mkinitcpio"
                            ;;
                          2)
                            $DIALOG ${FLAGS_DIALOG[@]} \
                              --msgbox "\
Now edit the Initial Ramdisk Configuration File ...\n\
\n\
e.g. remove modules if not required:\n\
· i915        – Intel Graphics\n\
· nouveau     – nVIDEA Graphics\n\
\n\
e.g. remove hooks if not required:\n\
· keymap      – add console keymap to ramdisk image\n\
· consolefont – add console font to ramdisk image\n\
· encrypt     – support encrypted root device\n\
· usr         – support /usr and /usr/local on separate partitions\n\
· shutdown    – add dismount capabilities for usr and encrypt hook\n" ${WIDGET_DIM};
                            echo; echo;

                            # customize /mnt/etc/mkinitcpio.conf
                            #   e.g.: adjust MODULES and HOOKS as described in libreboot how-to:
                            #   https://libreboot.org/docs/gnulinux/encrypted_parabola.html#install-the-base-system
                            cp --backup=numbered "$config_mkinitcpio" "$config_mkinitcpio".bak
                            nano "$config_mkinitcpio"
                            ;;
                          3)
                            # make initramfs
                            make_initramfs
                            ;;
                        esac
                        echo "... done with job $x: “${checklist_mkinitcpio[$((x*3-2))]}”"
                        hitenter || abort
                      done
                      echo "... Mkinitcpio Configuration Checklist processed."
                      hitenter || abort
                    }
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac
              }
              ;;
            13)   # GRUB bootloader options
              [ -n "$FLAG_DISK" -a -n "$FLAG_ROOT" ] && {
                checklist_grub=(
                  1 "Install GRUB Package"                                      on
                  2 "Install GRUB Bootloader${DISK_SYSTEM:+ on $DISK_SYSTEM}"   off
                  3 "Generate GRUB Configuration File ..."                      on
                )
                feedback=$( \
                  $DIALOG ${FLAGS_DIALOG[@]} \
                    --cancel-label "Abort" \
                    --checklist \
                      "GRUB Bootloader Options" \
                      ${MENUWIDGET_DIM} \
                      "${checklist_grub[@]}"; \
                )
                case $? in
                  0)
                    echo; echo;
                    [ -n "$feedback" ] && {
                      echo "Process GRUB Checklist ..."
                      sleep $PROCESS_DELAY
                      echo
                      for x in $feedback; do
                        echo "Starting job $x: “${checklist_grub[$((x*3-2))]}” ...";
                        sleep $PROCESS_DELAY
                        case $x in
                          1)
                            install_packages "${packages_GRUB[*]}"
                            ;;
                          2)
                            echo "#!/bin/bash                                                               " >  /mnt/grubInstall.sh
                            echo "                                                                          " >> /mnt/grubInstall.sh
                            echo "notool() {                                                                " >> /mnt/grubInstall.sh
                            echo "  local -r tool=\"\$1\"                                                   " >> /mnt/grubInstall.sh
                            echo "  echo \"Missing tool in chroot environment: \$tool\"                     " >> /mnt/grubInstall.sh
                            echo "  exit 1                                                                  " >> /mnt/grubInstall.sh
                            echo "}                                                                         " >> /mnt/grubInstall.sh
                            echo "                                                                          " >> /mnt/grubInstall.sh
                            echo "# tool check                                                              " >> /mnt/grubInstall.sh
                            echo "[ -z \"\$(command -v grub-install)\" ] && notool 'grub-install'           " >> /mnt/grubInstall.sh
                            echo "                                                                          " >> /mnt/grubInstall.sh
                            echo "grub-install ${DISK_SYSTEM}                                               " >> /mnt/grubInstall.sh
                            chroot_exec "/mnt/grubInstall.sh" || abort
                            ;;
                          3)
                            radiolist_GRUB=(
                              1 "Generate GRUB Standard Configuration"           "${FLAG_PLAIN:-off}"
                              2 "Generate GRUB Configuration, Encrypted Disks"   "${FLAG_CRYPT:-off}"
                            )
                            feedback2=$( \
                              $DIALOG ${FLAGS_DIALOG[@]} \
                                --cancel-label "Abort" \
                                --radiolist "Type of GRUB Configuration File" ${MENUWIDGET_DIM} "${radiolist_GRUB[@]}"
                            )
                            case $? in
                              0)
                                echo; echo;
                                case $feedback2 in
                                  1)
                                    echo "#!/bin/bash                                                                                 " >  /mnt/grubConfig.sh
                                    echo "                                                                                            " >> /mnt/grubConfig.sh
                                    echo "notool() {                                                                                  " >> /mnt/grubConfig.sh
                                    echo "  local -r tool=\"\$1\"                                                                     " >> /mnt/grubConfig.sh
                                    echo "  echo \"Missing tool in chroot environment: \$tool\"                                       " >> /mnt/grubConfig.sh
                                    echo "  exit 1                                                                                    " >> /mnt/grubConfig.sh
                                    echo "}                                                                                           " >> /mnt/grubConfig.sh
                                    echo "                                                                                            " >> /mnt/grubConfig.sh
                                    echo "# tool check                                                                                " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v cp)\" ] && notool 'cp'                                                 " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v mv)\" ] && notool 'mv'                                                 " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v sed)\" ] && notool 'sed'                                               " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v mkdir)\" ] && notool 'mkdir'                                           " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v grub-mkconfig)\" ] && notool 'grub-mkconfig'                           " >> /mnt/grubConfig.sh
                                    echo "                                                                                            " >> /mnt/grubConfig.sh
                                    echo "cp /etc/default/grub /etc/default/grub.bak                                                  " >> /mnt/grubConfig.sh
                                    echo "mkdir -p /boot/grub                                                                         " >> /mnt/grubConfig.sh
                                    echo "sed -r -i                                                                                 \\" >> /mnt/grubConfig.sh
                                    echo "  -e \"/GRUB_CMDLINE_LINUX=/cGRUB_CMDLINE_LINUX=\\\"${swapvol:+resume=${swapvol}}\\\"\"   \\" >> /mnt/grubConfig.sh
                                    echo "    /etc/default/grub                                                                       " >> /mnt/grubConfig.sh
                                    echo "sed -r -i                                                                                 \\" >> /mnt/grubConfig.sh
                                    echo "  -e \"/GRUB_ENABLE_CRYPTODISK/s/^/#/;\"                                                  \\" >> /mnt/grubConfig.sh
                                    echo "    /etc/default/grub                                                                       " >> /mnt/grubConfig.sh
                                    echo "grub-mkconfig -o /boot/grub/grub.cfg                                                        " >> /mnt/grubConfig.sh
                                    echo "mv /etc/default/grub.bak /etc/default/grub                                                  " >> /mnt/grubConfig.sh
                                    chroot_exec "/mnt/grubConfig.sh" || abort
                                    ;;
                                  2)
                                    get_device '/mnt/' mountpoints_assigned partitions_processed cryptdev
                                    echo "#!/bin/bash                                                                                                                         " >  /mnt/grubConfig.sh
                                    echo "                                                                                                                                    " >> /mnt/grubConfig.sh
                                    echo "notool() {                                                                                                                          " >> /mnt/grubConfig.sh
                                    echo "  local -r tool=\"\$1\"                                                                                                             " >> /mnt/grubConfig.sh
                                    echo "  echo \"Missing tool in chroot environment: \$tool\"                                                                               " >> /mnt/grubConfig.sh
                                    echo "  exit 1                                                                                                                            " >> /mnt/grubConfig.sh
                                    echo "}                                                                                                                                   " >> /mnt/grubConfig.sh
                                    echo "                                                                                                                                    " >> /mnt/grubConfig.sh
                                    echo "# tool check                                                                                                                        " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v cp)\" ] && notool 'cp'                                                                                         " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v mv)\" ] && notool 'mv'                                                                                         " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v sed)\" ] && notool 'sed'                                                                                       " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v mkdir)\" ] && notool 'mkdir'                                                                                   " >> /mnt/grubConfig.sh
                                    echo "[ -z \"\$(command -v grub-mkconfig)\" ] && notool 'grub-mkconfig'                                                                   " >> /mnt/grubConfig.sh
                                    echo "                                                                                                                                    " >> /mnt/grubConfig.sh
                                    echo "cp /etc/default/grub /etc/default/grub.bak                                                                                          " >> /mnt/grubConfig.sh
                                    echo "mkdir -p /boot/grub                                                                                                                 " >> /mnt/grubConfig.sh
                                    echo "sed -r -i                                                                                                                         \\" >> /mnt/grubConfig.sh
                                    echo "  -e \"/GRUB_CMDLINE_LINUX=/cGRUB_CMDLINE_LINUX=\\\"cryptdevice=/dev/${cryptdev%${CRYPT_SUFFIX}}\:${cryptdev} hibernate=no\\\"\"  \\" >> /mnt/grubConfig.sh
                                    echo "    /etc/default/grub                                                                                                               " >> /mnt/grubConfig.sh
                                    echo "sed -r -i -e \"/GRUB_ENABLE_CRYPTODISK/s/^#//;\" /etc/default/grub                                                                  " >> /mnt/grubConfig.sh
                                    echo "grub-mkconfig -o /boot/grub/grub.cfg                                                                                                " >> /mnt/grubConfig.sh
                                    echo "mv /etc/default/grub.bak /etc/default/grub                                                                                          " >> /mnt/grubConfig.sh
                                    chroot_exec "/mnt/grubConfig.sh" || abort
                                    ;;
                                esac
                                ;;
                              *)
                                echo; echo;
                                abort
                                ;;
                            esac
                            ;;
                        esac
                        echo "... done with job $x: “${checklist_grub[$((x*3-2))]}”"
                        hitenter || abort
                      done
                      echo "... GRUB Checklist processed."
                      hitenter || abort
                    }
                    ;;
                  *)
                    echo; echo;
                    abort
                    ;;
                esac
              }
              ;;
            14)   # Live System: dismount partitions, close encryption
              dismount_mountpoints
              close_encryption
              ;;
          esac
          echo "... done with job $i: “${checklist_main[$((i*3-2))]}”"
          hitenter || abort
        done
        echo "... Main Checklist processed."
        echo "Good Luck!"
        echo
      }
      ;;
    *)
      echo; echo;
      abort
      ;;
  esac
}

# check tools
declare -r SED=$(command -v sed);        [ -z "$SED" ] && notool 'sed';
declare -r DIALOG=$(command -v dialog);  [ -z "$DIALOG" ] && notool 'dialog';

# globals
declare -r -a FLAGS_DIALOG=("--stdout" "--no-shadow" "--title Parabola-Setup")

# start
fillscreen
checkperm
main "$@"

##>! @endcond