#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

true "$BASH_SOURCE INFO: begin"

#printf "%s\n" "INFO: Currently running script: $BASH_SOURCE"

## {{ Sanity Tests.

dist_build_missing_dependency() {
   error "dist_build_missing_dependency
programs_to_check_installed_item: $1

Did you install dependencies as mentioned in build documentation chapter
Host Preparation
?"
   true
}

variables_script_sanity_test() {
   local dist_build_programs_to_check_installed_list programs_to_check_installed_item
   dist_build_programs_to_check_installed_list="logname whoami dirname basename awk grep"

   for programs_to_check_installed_item in $dist_build_programs_to_check_installed_list ; do
      $SUDO_TO_ROOT command -v "$programs_to_check_installed_item" >/dev/null || dist_build_missing_dependency "$programs_to_check_installed_item"
   done
}

variables_script_sanity_test
bash -n "$BASH_SOURCE"

## }}

path_variable_adjustments() {
   local path_part path_array local_sbin_found standard_sbin_found

   ## Manual testing.
   ## CI has the following and lacks any mention of 'sbin' in the PATH variable.
   #PATH="/usr/local/bin:/usr/bin:/bin:/usr/games"

   old_path="$PATH"
   true "INFO: old_path: $old_path"
   ## Example PATH:
   ## /home/user/derivative-maker/help-steps:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
   ## Example PATH on CI:
   #PATH="/usr/local/bin:/usr/bin:/bin:/usr/games"

   IFS=':' read -ra path_array <<< "$PATH"

   new_path="$PATH"
   for path_part in "${path_array[@]}"; do
      if [ "$path_part" = "/usr/local/sbin" ]; then
         local_sbin_found=yes
      fi
      if [ "$path_part" = "/usr/sbin" ]; then
         standard_sbin_found=yes
      fi
   done

   if [ ! "$local_sbin_found" = "yes" ]; then
      new_path="/usr/local/sbin:$new_path"
   fi

   if [ ! "$standard_sbin_found" = "yes" ]; then
      new_path="$new_path:/usr/sbin"
   fi
}

path_variable_adjustments
export PATH="$new_path"
true "INFO: new_path: $PATH"
## Example PATH:
## /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

MYDIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" && pwd )"

[ -n "$user_name" ] || user_name=$(whoami) || true
[ -n "$user_name" ] || user_name="$USER"
[ -n "$user_name" ] || user_name="$(logname)" || true
[ -n "$user_name" ] || user_name="$SUDO_USER"
if [ "$user_name" = "" ]; then
   error "Variable user_name is empty."
fi
export user_name

[ -n "$SUDO_TO_ROOT" ] || SUDO_TO_ROOT="sudo --non-interactive"
[ -n "$HOMEVAR_VBOX_TEMP" ] || HOMEVAR_VBOX_TEMP="/home/dm-vbox-temp"
export HOMEVAR_VBOX_TEMP

## Use 'sudo' with '-D $HOMEVAR_VBOX_TEMP' ('--chdir') to avoid 'VBoxManage' error.
#> VBoxManage: error: Could not create the directory '.' (VERR_ACCESS_DENIED)
[ -n "$SUDO_TO_VBOX_TEMP" ] || SUDO_TO_VBOX_TEMP="sudo --non-interactive -D $HOMEVAR_VBOX_TEMP -u dm-vbox-temp"

[ -n "$HOMEVAR" ] || HOMEVAR="/home/$user_name"
export HOMEVAR
[ -n "$binary_build_folder_dist" ] || binary_build_folder_dist="$HOMEVAR/derivative-binary"
export binary_build_folder_dist

MYDIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" && pwd )"
[ -n "$source_code_folder_dist" ] || source_code_folder_dist="$(dirname -- "$MYDIR")"
export source_code_folder_dist

build_script_main="${source_code_folder_dist}/derivative-maker"

[ -n "$dist_parent_folder" ] || dist_parent_folder="$(dirname -- "$source_code_folder_dist")"
[ -n "$dist_developer_meta_files_folder" ] || dist_developer_meta_files_folder="${source_code_folder_dist}/packages/kicksecure/developer-meta-files"

[ -n "$dist_source_parentdir" ] || dist_source_parentdir="$(dirname -- "$source_code_folder_dist")"
export dist_source_parentdir

[ -n "$dist_source_help_steps_folder" ] || dist_source_help_steps_folder="${source_code_folder_dist}/help-steps"
export dist_source_help_steps_folder

[ -n "$str_replace_tool" ] || str_replace_tool="${source_code_folder_dist}/packages/kicksecure/helper-scripts/usr/bin/str_replace"
[ -n "$str_replace_many_tool" ] || str_replace_many_tool="${source_code_folder_dist}/packages/kicksecure/helper-scripts/usr/bin/str-replace-many"

[ -n "$architecture_all_list" ] || architecture_all_list=( amd64 arm64 armel armhf hurd-i386 hurd-amd64 i386 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc ppc64 ppc64el s390x sparc source )

cd "$source_code_folder_dist"

[ -n "$dist_aptgetopt_file" ] || dist_aptgetopt_file="$binary_build_folder_dist/30_derivative-maker.conf"
export dist_aptgetopt_file
## XXX: sudo with '--'
$SUDO_TO_ROOT rm -f -- "$dist_aptgetopt_file"

## Cannot export bash array.
#APTGETOPT=()
#export APTGETOPT
export APTGETOPT_SERIALIZED

## Debugging.
#declare -p APTGETOPT
#printf "%s\n" "$APTGETOPT_SERIALIZED"

aptgetopt_add() {
   local opt opt_file
   opt="$1"

   APTGETOPT+=("-o")
   APTGETOPT+=("$opt")
   APTGETOPT_SERIALIZED="$(printf '%s\n' "${APTGETOPT[@]}")"

   if [[ "$opt" =~ [Pp]roxy ]]; then
      return 0
   fi
   APTGETOPT_WITHOUT_APT_CACHE+=("-o")
   APTGETOPT_WITHOUT_APT_CACHE+=("$opt")
}

aptgetopt_conf_add () {
   mkdir --parents -- "$binary_build_folder_dist/"
   printf "%s\n" "$1" | tee --append -- "$dist_aptgetopt_file" >/dev/null
}

## Avoiding "perl: warning: Setting locale failed." as suggested on
## https://wiki.ubuntu.com/DebootstrapChroot and
## https://lists.debian.org/debian-amd64/2005/08/msg00249.html.
LANG="C"
export LANG
LC_ALL="C"
export LC_ALL

## Deterministic.
LC_ALL=C.UTF-8
TZ=UTC
export LC_ALL TZ

## Disable uwt while building Whonix,
## because it is not functional while building Whonix from source code.
[ -n "$UWT_DEV_PASSTHROUGH" ] || UWT_DEV_PASSTHROUGH="1"
export UWT_DEV_PASSTHROUGH

## used by mmdebstrap
## dpkg-parsechangelog (from package dpkg-dev) is not available before dependencies are installed.
if command -v dpkg-parsechangelog &>/dev/null ; then
   SOURCE_DATE_EPOCH="$(dpkg-parsechangelog -STimestamp)"
else
   true "INFO: SOURCE_DATE_EPOCH not available yet because dpkg-parsechangelog has not been installed yet."
fi

## TODO: do not export without thinking this through since also used by debhelper
export SOURCE_DATE_EPOCH

#[ -n "$DEBDEBUG" ] || export DEBDEBUG="1"

[ -n "$tpo_downloader_debug" ] || tpo_downloader_debug="1"
export tpo_downloader_debug

if [ ! "$dist_build_one_parsed" = "true" ]; then
   MINUS_X_SET="0"
   test -o xtrace || { MINUS_X_SET="$?" ; true; };
   if [ "$MINUS_X_SET" = "0" ]; then
      ## -x was set
      bash -n "${source_code_folder_dist}/help-steps/parse-cmd"
      source "${source_code_folder_dist}/help-steps/parse-cmd"
      dist_build_one_parse_cmd "$@"
   else
      ## -x was not set
      bash -n "${source_code_folder_dist}/help-steps/parse-cmd"
      source "${source_code_folder_dist}/help-steps/parse-cmd"
      dist_build_one_parse_cmd "$@"
   fi
   dist_build_one_parsed="true"
   export dist_build_one_parsed
fi

## dist_build_redistributable=true is set in help-steps/dm-build-official
if [ "$dist_build_redistributable" = "true" ]; then
   ## Enable binary derivative repository by default for official builds.
   ## Same as: '--repo true'
   ## Needs to be set before parsing buildconfig.d folder / dist_build_source_config_dir function!
   build_remote_repo_enable="true"
   export build_remote_repo_enable
   if [ "$dist_build_target_arch" = "amd64" ]; then
      ## Make sure official builds for the Intel/AMD64 architecture
      ## come with Tor Browser installed by default.
      ## Fail closed by default in case of Tor Browser download issues.
      ## Same as: '--tb closed'
      [ -n "$anon_shared_inst_tb" ] || anon_shared_inst_tb="closed"
   else
      ## Tor Browser is not yet available at time of writing for ARM64 and
      ## other architecture.
      ## TODO: reproducible builds
      [ -n "$anon_shared_inst_tb" ] || anon_shared_inst_tb="open"
   fi
else
   ## Non-redistributable builds use '--tb open' by default.
   [ -n "$anon_shared_inst_tb" ] || anon_shared_inst_tb="open"
fi
## Variable 'anon_shared_inst_tb' only has an effect if package 'tb-updater' is installed.
export anon_shared_inst_tb

## repository-dist-initializer
repository_dist_initializer_setup() {
   [ -n "${binary_build_folder_dist}" ] || error "repository_dist_initializer_setup: variable binary_build_folder_dist missing!"
   [ -n "${CHROOT_FOLDER}" ] || error "repository_dist_initializer_setup: variable CHROOT_FOLDER missing!"

   ## Enable generation of repository-dist config file
   true "INFO: build_remote_repo_enable: $build_remote_repo_enable"
   if [ "${build_remote_repo_enable}" = 'true' ]; then
      printf "%s\n" "${DERIVATIVE_APT_REPOSITORY_OPTS}" | sponge -- "${binary_build_folder_dist}/derivative_apt_repository_opts"

      ## Debugging.
      true "INFO: sudo test"
      $SUDO_TO_ROOT test -d /usr

      $SUDO_TO_ROOT mkdir --parents -- "${CHROOT_FOLDER}/var/lib/repository-dist/"
      $SUDO_TO_ROOT cp -- "${binary_build_folder_dist}/derivative_apt_repository_opts" "${CHROOT_FOLDER}/var/lib/repository-dist/derivative_apt_repository_opts"
   else
      rm -f -- "${binary_build_folder_dist}/derivative_apt_repository_opts"
   fi
}

export dist_build_sources_list_primary

## https://forums.whonix.org/t/kicksecure-etc-hostname-etc-hosts/10919
[ -n "$dist_build_hostname" ] || dist_build_hostname="localhost"

if [ "$dist_build_flavor" = "internalrun" ]; then
   [ -n "$dist_build_type_long" ] || dist_build_type_long="internalrun"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="internalrun"
fi

if [ "$dist_build_flavor" = "dist-installer-cli" ]; then
   [ -n "$dist_build_type_long" ] || dist_build_type_long="dist-installer-cli"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="dist-installer-cli"
fi

if [ "$dist_build_flavor" = "whonix-gateway-lxqt" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Gateway"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Gateway-LXQt"
   [ -n "$VMRAM" ] || VMRAM="1280"
   [ -n "$VRAM" ] || VRAM="128"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="gateway"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="LXQt"
   [ -n "$dist_build_gui" ] || dist_build_gui="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-gateway-vm-gui-lxqt "
fi

if [ "$dist_build_flavor" = "whonix-gateway-rpi" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Gateway"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Gateway-RPi"
   [ -n "$VMRAM" ] || VMRAM="768"
   [ -n "$VRAM" ] || VRAM="16"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="gateway"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="RPi"
   ## TODO
   [ -n "$dist_build_gui" ] || dist_build_gui="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   #[ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-gateway-rpi "
   error "${red}${bold}dist_build_flavor $dist_build_flavor is not implemented.${reset}"
fi

if [ "$dist_build_flavor" = "whonix-gateway-cli" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Gateway"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Gateway-CLI"
   [ -n "$VMRAM" ] || VMRAM="768"
   [ -n "$VRAM" ] || VRAM="16"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="gateway"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="CLI"
   [ -n "$dist_build_gui" ] || dist_build_gui="false"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-gateway-vm-server "
fi

if [ "$dist_build_flavor" = "whonix-workstation-lxqt" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Workstation"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Workstation-LXQt"
   [ -n "$VMRAM" ] || VMRAM="2048"
   [ -n "$VRAM" ] || VRAM="128"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="workstation"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="LXQt"
   [ -n "$dist_build_gui" ] || dist_build_gui="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-workstation-vm-gui-lxqt "
fi

if [ "$dist_build_flavor" = "whonix-workstation-cli" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Workstation"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Workstation-CLI"
   [ -n "$VMRAM" ] || VMRAM="768"
   [ -n "$VRAM" ] || VRAM="16"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="workstation"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="CLI"
   [ -n "$dist_build_gui" ] || dist_build_gui="false"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-workstation-vm-server "
fi

if [ "$dist_build_flavor" = "whonix-custom-workstation" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Custom-Workstation"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Custom-Workstation"
   [ -n "$VMRAM" ] || VMRAM="2048"
   [ -n "$VRAM" ] || VRAM="128"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="custom-workstation"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="CUSTOM"
   [ -n "$dist_build_gui" ] || dist_build_gui="false"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   #[ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" none "
fi

if [ "$dist_build_flavor" = "whonix-host-cli" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Host"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Host-CLI"
   [ -n "$VMRAM" ] || VMRAM="768"
   [ -n "$VRAM" ] || VRAM="16"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="whonix-host"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="CLI"
   [ -n "$dist_build_gui" ] || dist_build_gui="false"
   [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   error "${red}${bold}dist_build_flavor $dist_build_flavor is not implemented.${reset}"
fi

if [ "$dist_build_flavor" = "whonix-host-lxqt" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Whonix-Host"
   [ -n "$VMNAME" ] || VMNAME="Whonix-Host-LXQt"
   [ -n "$VMRAM" ] || VMRAM="2048"
   [ -n "$VRAM" ] || VRAM="128"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="whonix-host"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="whonix"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="LXQt"
   [ -n "$dist_build_gui" ] || dist_build_gui="true"
   [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="host"
   ## TODO: Do not hardcode to VirtualBox.
   #[ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" whonix-lxqt-host-virtualbox "
   error "${red}${bold}dist_build_flavor $dist_build_flavor is not implemented.${reset}"
fi

if [ "$dist_build_flavor" = "kicksecure-cli" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Kicksecure"
   [ -n "$VMNAME" ] || VMNAME="Kicksecure-CLI"
   [ -n "$VMRAM" ] || VMRAM="768"
   [ -n "$VRAM" ] || VRAM="16"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="kicksecure"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="CLI"
   [ -n "$dist_build_gui" ] || dist_build_gui="false"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="localhost"
   if [ "$dist_build_type" = "vm" ]; then
      [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="false"
      [ -n "$dist_build_type_long" ] || dist_build_type_long="kicksecure"
      [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" kicksecure-vm-server "
   elif [ "$dist_build_type" = "host" ]; then
      [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="true"
      [ -n "$dist_build_type_long" ] || dist_build_type_long="kicksecure-host"
      [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" kicksecure-baremetal-server "
   fi
fi

if [ "$dist_build_flavor" = "kicksecure-lxqt" ]; then
   [ -n "$SHORT_VMNAME" ] || SHORT_VMNAME="Kicksecure"
   [ -n "$VMNAME" ] || VMNAME="Kicksecure-LXQt"
   [ -n "$VMRAM" ] || VMRAM="2048"
   [ -n "$VRAM" ] || VRAM="128"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="kicksecure"
   [ -n "$dist_build_desktop" ] || dist_build_desktop="LXQt"
   [ -n "$dist_build_gui" ] || dist_build_gui="true"
   #[ -n "$dist_build_hostname" ] || dist_build_hostname="localhost"
   if [ "$dist_build_type" = "vm" ]; then
      [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="false"
      [ -n "$dist_build_type_long" ] || dist_build_type_long="kicksecure"
      [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" kicksecure-vm-gui-lxqt "
   elif [ "$dist_build_type" = "host" ]; then
      [ -n "$dist_build_host_operating_system" ] || dist_build_host_operating_system="true"
      [ -n "$dist_build_type_long" ] || dist_build_type_long="kicksecure-host"
      [ -n "$flavor_meta_packages_to_install" ] || flavor_meta_packages_to_install=" kicksecure-baremetal-gui-lxqt "
   fi
fi

## derivative_name_list is used by:
## - help-steps/variables to identify valid derivative names.
## - help-steps/create-local-temp-apt-repo to create one or multiple local APT repositories.
## - help-steps/cleanup-files to clean one or multiple folders.
## - help-steps/unchroot-raw to unmount one or multiple local APT repositories.
## - buildconfig.d/30_pkg_list.conf to create a list of packages to be built.
## - buildconfig.d/25_apt_sources.conf to create a APT URIs.
## - build-steps.d/*_create-debian-packages to iterate through one or multiple package folders.

if [ "$dist_build_internal_run" = "true" ]; then
   if [ "$VMNAME" = "" ]; then
      VMNAME="internal"
      export VMNAME
   fi
   [ -n "$derivative_name_list" ] || derivative_name_list="kicksecure whonix"
   [ -n "$dist_build_type_long" ] || dist_build_type_long="internalrun"
   [ -n "$dist_build_type_short" ] || dist_build_type_short="internalrun"
fi

export dist_build_type_long

export VMNAME VMRAM VRAM

vm_multiple=false
if [ "${dist_build_type_long}" = "workstation" ]; then
   vm_multiple=true
   ## dist_build_desktop could be KDE, CLI, Xfce, LXQt, RPi or CUSTOM
   [ -n "$vm_names_to_be_exported" ] || vm_names_to_be_exported="Whonix-Gateway-${dist_build_desktop} Whonix-Workstation-${dist_build_desktop}"
fi
if [ "${dist_build_type_long}" = "custom-workstation" ]; then
   [ -n "$vm_names_to_be_exported" ] || vm_names_to_be_exported="${VMNAME}"
fi
if [ "${dist_build_type_short}" = "kicksecure" ]; then
   [ -n "$vm_names_to_be_exported" ] || vm_names_to_be_exported="${VMNAME}"
fi

maybe_disable_dist_build_windows_installer() {
   if [ "$dist_build_internal_run" = "true" ]; then
      true "$BASH_SOURCE INFO: dist_build_internal_run set to true, skipping $FUNCNAME, ok."
   else
      true "$BASH_SOURCE INFO: dist_build_internal_run is not set to true, therefore: dist_build_windows_installer=false"
      dist_build_windows_installer=false
   fi
}

if [ "$dist_build_type_short" = "kicksecure" ]; then
   [ -n "$derivative_name_list" ] || derivative_name_list="kicksecure"
   [ -n "$dist_build_type_short_pretty" ] || dist_build_type_short_pretty="Kicksecure"
   [ -n "$dist_server_with_upload_location_list_list" ] || dist_server_with_upload_location_list_list="kicksecure.com"
   [ -n "$project_clearnet" ] || project_clearnet="kicksecure.com"
   true "$BASH_SOURCE INFO: dist_build_type_short is 'kicksecure'. Build Whonix Windows Installer only for Whonix LXQt for VirtualBox. Therefore: maybe_disable_dist_build_windows_installer"
   maybe_disable_dist_build_windows_installer
elif [ "$dist_build_type_short" = "whonix" ]; then
   [ -n "$derivative_name_list" ] || derivative_name_list="kicksecure whonix"
   [ -n "$dist_build_type_short_pretty" ] || dist_build_type_short_pretty="Whonix"
   [ -n "$dist_server_with_upload_location_list_list" ] || dist_server_with_upload_location_list_list="whonix.org"
   [ -n "$project_clearnet" ] || project_clearnet="whonix.org"
elif [ "$dist_build_type_short" = "dist-installer-cli" ]; then
   [ -n "$derivative_name_list" ] || derivative_name_list="kicksecure whonix"
   [ -n "$dist_build_type_short_pretty" ] || dist_build_type_short_pretty="dist-installer-cli"
   ## XXX: Does not support lists.
   # -n "$dist_server_with_upload_location_list_list" ] || dist_server_with_upload_location_list_list="kicksecure.com whonix.org"
   [ -n "$project_clearnet" ] || project_clearnet="kicksecure.com"
   true "$BASH_SOURCE INFO: dist_build_type_short is 'dist-installer-cli'. Build Whonix Windows Installer only for Whonix LXQt for VirtualBox. Therefore: maybe_disable_dist_build_windows_installer"
   maybe_disable_dist_build_windows_installer
   VMNAME=dist-installer-cli
elif [ "$dist_build_type_short" = "internalrun" ]; then
   true
else
   error "unknown dist_build_type_short!"
fi

## example dist_build_desktop_lowercase:
## lxqt
[ -n "$dist_build_desktop_lowercase" ] || dist_build_desktop_lowercase=$(printf "%s\n" "$dist_build_desktop" | tr '[:upper:]' '[:lower:]')

if [ ! "$dist_build_desktop_lowercase" = "lxqt" ] ; then
   true "$BASH_SOURCE INFO: dist_build_desktop_lowercase is '$dist_build_desktop_lowercase'. Not 'lxqt'. Build Whonix Windows Installer only for Whonix LXQt for VirtualBox. Therefore: maybe_disable_dist_build_windows_installer"
   maybe_disable_dist_build_windows_installer
fi

## vmsize 100 GB does not matter because grml-debootstrap creates sparse files,
## i.e. only space, which gets actually filled up, will take disk space.

if [ "$build_dry_run" = "true" ]; then
   [ -n "$VMSIZE" ] || VMSIZE="1M"
fi
[ -n "$VMSIZE" ] || VMSIZE="100G"
export VMSIZE

## Disk identifier for grml-debootstrap.
## https://github.com/grml/grml-debootstrap/pull/28
[ -n "$DISK_IDENTIFIER" ] || DISK_IDENTIFIER='26ada0c0-1165-4098-884d-aafd2220c2c6'
export DISK_IDENTIFIER

if [ "$dist_build_install_to_root" = "true" ]; then
   [ -n "$CHROOT_FOLDER" ] || CHROOT_FOLDER=""
else
   [ -n "$CHROOT_FOLDER" ] || CHROOT_FOLDER="$binary_build_folder_dist/${VMNAME}_image"
fi
export CHROOT_FOLDER

true "$BASH_SOURCE INFO: CHROOT_FOLDER: $CHROOT_FOLDER"

## {{{ initramfs

## binutils dmsetup:
##     https://packages.debian.org/bullseye/dmsetup lists 'Recommends:' which
##     are actually required for a functional boot process.
## pigz:
##     maybe not required but useful.
## dracut-config-rescue:
##     Not actually doing anything.
##     https://www.kicksecure.com/wiki/Dev/todo#investigate_dracut-config-rescue
## dracut-config-generic:
##     Actively detrimental. Introduces a file at
##     /usr/lib/dracut/dracut.conf.d/50-generic.conf which sets 'hostonly="no",
##     overriding /etc/dracut.conf.d/30-dist-base-files.conf.
[ -n "$BUILD_INITRAMFS_DRACUT" ] || BUILD_INITRAMFS_DRACUT="dracut dracut-live binutils dmsetup pigz"

[ -n "$BUILD_INITRAMFS_PKGS" ] || BUILD_INITRAMFS_PKGS="$BUILD_INITRAMFS_DRACUT"

if printf "%s\n" "$BUILD_INITRAMFS_PKGS" | grep --quiet -- "dracut" ; then
   ## INITRD_GENERATOR_OPTS gets read by grml-debootstrap and passed to dracut and is also
   ## read by build-steps.d/*_install-packages
   ##
   ## Worked but issue:
   ## https://forums.kicksecure.com/t/iso-error-message-during-boot-mount-sysroot-special-device-liveos-rootfs-does-not-exist/418
   [ -n "$INITRD_GENERATOR_OPTS" ] || INITRD_GENERATOR_OPTS='--add dmsquash-live --add overlayfs --add bash'
   export INITRD_GENERATOR_OPTS
fi

source_dracut_disable_config_snippet="$source_code_folder_dist/packages/kicksecure/initializer-dist/usr/share/initializer-dist/dracut/90-derivative-maker-build.conf"
target_dracut_disable_config_snippet="$CHROOT_FOLDER/etc/dracut.conf.d/90-derivative-maker-build.conf"

source_dkms_suppress_mok_snippet="$source_code_folder_dist/packages/kicksecure/initializer-dist/usr/share/initializer-dist/dkms/90-derivative-maker-build.conf"
target_dkms_suppress_mok_snippet="$CHROOT_FOLDER/etc/dkms/framework.conf.d/90-derivative-maker-build.conf"

true "${cyan}$BASH_SOURCE INFO: BUILD_INITRAMFS_PKGS (--initramfs): $BUILD_INITRAMFS_PKGS${reset}"

## }}}

if [ "$VMNAME" = "unknown" ]; then
   true "variables ERROR: VMNAME is unknown. Please report this bug!"
   exit 1
fi

if [ "$dist_build_internal_run" = "true" ]; then
   true "$BASH_SOURCE INFO: Internal run."
else
   true "$BASH_SOURCE INFO: VMNAME is $VMNAME"
fi

if [ "$VMNAME" = "" ]; then
   MSG="${red}${bold}variables ERROR: VMNAME is empty! Please report this bug!${reset}"
   printf "%s\n" "$MSG"
   error "$MSG"
fi

[ -n "$XZ_OPT" ] || XZ_OPT="--threads=8"
export XZ_OPT

if [ "$dist_build_unsafe_io" = "true" ]; then
   eatmydata_install="true"
   aptgetopt_add "Dpkg::Options::=--force-unsafe-io"
   aptgetopt_conf_add "Dpkg::Options:: \"--force-unsafe-io\";"
   libeatmydata_file=/usr/lib/*-linux-gnu/libeatmydata.so
   if test -f "$libeatmydata_file" ; then
      true "INFO: eatmydata installed, preloading."
      if [ -z "$LD_PRELOAD" ]; then
         LD_PRELOAD="$libeatmydata_file"
      else
         LD_PRELOAD="${LD_PRELOAD}:${libeatmydata_file}"
      fi
      export LD_PRELOAD
      SUDO_TO_ROOT="$SUDO_TO_ROOT LD_PRELOAD=$LD_PRELOAD"
   else
      true "INFO: eatmydata not yet installed, not yet preloading."
   fi
   sync() {
      true "$FUNCNAME: Not running $FUNCNAME, because using '--unsafe-io true'."
   }
fi

## use approx by default
## required for --connection clearnet
## Port 9977 defined by approx/approx.conf
## REPO_PROXY is no longer used now that we're using approx.
#[ -n "$REPO_PROXY" ] || REPO_PROXY="http://127.0.0.1:9977"
[ -n "${APPROX_PROXY_ENABLE}" ] || APPROX_PROXY_ENABLE='yes'

if [ -n "${APPROX_PROXY_ENABLE}" ]; then
   ## apt parameters must be without quotes
   ## apt parameters must be without equals sign
   ## apt parameters must be without colon sign
   ## apt config file must be with quotes
   ## apt config file must be without equals sign
   ## apt config file must be trailing colon sign

   ## Obsolete now that we're using approx.
   #aptgetopt_add "Acquire::http::Proxy=${REPO_PROXY}"
   #aptgetopt_conf_add "Acquire::http::Proxy \"${REPO_PROXY}\";"

   #aptgetopt_add "Acquire::https::Proxy=${REPO_PROXY}"
   #aptgetopt_conf_add "Acquire::https::Proxy \"${REPO_PROXY}\";"

   ## https://forums.whonix.org/t/derivative-maker-fails-with-onion-sources/20200/8
   #aptgetopt_add "Acquire::tor::Proxy=${REPO_PROXY}"
   #aptgetopt_conf_add "Acquire::tor::Proxy \"${REPO_PROXY}\";"

   aptgetopt_add "Acquire::BlockDotOnion=false"
   aptgetopt_conf_add "Acquire::BlockDotOnion \"false\";"

   #DEBOOTSTRAP_PREFIX+=" env http_proxy=${REPO_PROXY} https_proxy=${REPO_PROXY} ALL_PROXY=${REPO_PROXY}"
   #COWBUILDER_PREFIX+=" env http_proxy=${REPO_PROXY} https_proxy=${REPO_PROXY} ALL_PROXY=${REPO_PROXY}"
   #LIVEBUILD_PREFIX+=" env http_proxy=${REPO_PROXY} https_proxy=${REPO_PROXY} ALL_PROXY=${REPO_PROXY}"
fi

## Help update-torbrowser and other software find the Tor server if using
## '--connection tor'.
if [ "$dist_build_sources_clearnet_or_onion" = 'onion' ]; then
   if [ -z "${CURL_PROXY}" ]; then
      ## TODO: Possibly allow customizing the server and port for this?
      ## HARDCODED.
      CURL_PROXY='--proxy socks5h://127.0.0.1:9050'
      export CURL_PROXY
   fi
fi

## Export COWBUILDER_PREFIX so it is available in make-helper.bsh.
export COWBUILDER_PREFIX

chroot_env_vars_var_remove_item="
   TEMP
   TEMPDIR
   TMP
   TMPDIR
"

for chroot_env_vars_var_remove_item in $chroot_env_vars_var_remove_item ; do
   if [ "$chroot_env_vars_var_remove_item" = "" ]; then
      true "INFO: variable $chroot_env_vars_var_remove_item is empty."
      continue
   fi
   if [ "$chroot_remove_env_list" = "" ]; then
      chroot_remove_env_list="--unset $chroot_env_vars_var_remove_item"
   else
      chroot_remove_env_list+=" --unset $chroot_env_vars_var_remove_item"
   fi
done

if [ "$dist_build_install_to_root" = "true" ]; then
   chroot_run() {
      $SUDO_TO_ROOT "$@"
   }
else
   chroot_run() {
      $SUDO_TO_ROOT env $chroot_remove_env_list chroot "$CHROOT_FOLDER" "$@"

      #$SUDO_TO_ROOT env $chroot_remove_env_list systemd-nspawn --directory="$CHROOT_FOLDER"
   }
fi

if [ "$no_git" = "1" ]; then
   [ -n "$git_bin" ] || git_bin="true"
else
   [ -n "$git_bin" ] || git_bin="git"
fi

## Otherwise errors out because there is a folder grml-debootstarp in the root source folder.
## Cannot use `which grml-debootstrap` because that would fail before grml-debootstrap gets installed.
#[ -n "$dist_build_grml_bin" ] || dist_build_grml_bin="$(which grml-debootstrap)"
[ -n "$dist_build_grml_bin" ] || dist_build_grml_bin="/usr/sbin/grml-debootstrap"

[ -n "$rsync_cmd" ] || rsync_cmd="rsync"

## TODO: hardlinks: rsync error Internal hashtable error: illegal key supplied
## --hard-links \
if [ "$rsync_opts" = "" ]; then
   rsync_opts="\
   --links \
   --safe-links \
   --owner \
   --group \
   --chown=root:www-data \
   --chmod=uog+r \
   --times \
   --sparse \
   --partial \
   --progress \
   --verbose"
fi

if [ "$build_dry_run" = "true" ]; then
   rsync_opts="$rsync_opts --dry-run"
fi

## TODO: auto retry function error handler trap lacks variables
## such as variable APTGETOPT.
## Would miss out on security related APT configuration options:
## apt-get --error-on=any / -o APT::Update::Error-Mode=any
[ -n "$dist_build_auto_retry" ] || dist_build_auto_retry="0"

[ -n "$dist_build_wait_auto_retry" ] || dist_build_wait_auto_retry="5"

## Sanity Test.
command -v "$git_bin" >/dev/null

[ -n "$DEB_INSTALL_FOLDER" ] || DEB_INSTALL_FOLDER="mnt/initialdeb"
export DEB_INSTALL_FOLDER

[ -n "$EMPTY_DIR" ] || EMPTY_DIR="/tmp/empty"
export EMPTY_DIR

[ -n "$derivative_maker" ] || derivative_maker=true
export derivative_maker

## {{{ dist_build_on_operating_system

if [ "$dist_build_on_operating_system_detect_skip" = "1" ]; then
   true "Probably run by prepare-build-machine script. lsb_release may not yet installed. Skipping setting dist_build_on_operating_system."
else
   ## Let's find out on which host operating system the build script is running.
   [ -n "$dist_build_on_operating_system" ] || dist_build_on_operating_system="$(lsb_release --short --i)"
   ## Converting dist_build_on_operating_system to lower case to make later if comparison easier.
   dist_build_on_operating_system="${dist_build_on_operating_system,,}"
   ## Example dist_build_on_operating_system: debian
   ## Example dist_build_on_operating_system: ubuntu
   ## XXX
   if [ "$dist_build_on_operating_system" = "whonix" ]; then
      dist_build_on_operating_system="debian"
   fi
fi

## }}}

## {{{ dist_build_current_git_head

## Get the ref (branch or commit) that we're currently at.
## NOTE: Cannot use end-of-options ("--").
[ -n "$dist_build_current_git_head" ] || dist_build_current_git_head="$($git_bin rev-parse HEAD)" || error 'Cannot get head commit ID!'

#printf "%s\n" "dist_build_current_git_head: $dist_build_current_git_head"

## }}}

## {{{ dist_build_version

## --always because travis-ci does not fetch tags.
temp="$($git_bin describe --always --abbrev=1000000000)"
## Examples temp:
## 10-13-g20e1b49ff27053784e3e9e163dfd4c98dced73f5
## 10.0.0.0.3-13-g20e1b49ff27053784e3e9e163dfd4c98dced73f5-developers-only

if [ "$dist_build_version" = "" ]; then
   dist_build_version="$temp"
   true "${cyan}INFO: Variable dist_build_version was unset. Auto detected. Set to: dist_build_version=${dist_build_version}${reset}"
else
   true "${cyan}INFO: Variable dist_build_version was already set to: dist_build_version=${dist_build_version}${reset}"
fi
unset temp

dist_build_version="$(printf "%s\n" "$dist_build_version" | sed "s|-developers-only||g")"
dist_build_version="$(printf "%s\n" "$dist_build_version" | sed "s|-testers-only||g")"
dist_build_version="$(printf "%s\n" "$dist_build_version" | sed "s|-stable||g")"

## Using `export`, so 70_log_build_version can read it.
export dist_build_version

## Example dist_build_version:
## 10.0.0.0.3-13-g20e1b49ff27053784e3e9e163dfd4c98dced73f5

## }}}

set_default_variable() {
  local var_name var_content
  var_name="$1"
  var_content="$2"

  if [ -z "${!var_name:-}" ]; then
    #printf "%s\n" "INFO: Variable '$var_name' is already set? No. - Setting: $var_name='$var_content'"
    eval "$var_name='$var_content'"
    return 0
  fi
  #printf "%s\n" "INFO: Variable '$var_name' is already set? Yes. - Already: $var_name='${!var_name}'"
}

if [ "${dist_build_source_archive}" = "true" ]; then
    set_default_variable dist_unified_name "derivative-maker-source"
elif [ "$dist_build_type_short" = "kicksecure" ]; then
    set_default_variable dist_unified_name "Kicksecure-${dist_build_desktop}"
elif [ "$dist_build_type_short" = "whonix" ]; then
    set_default_variable dist_unified_name "Whonix-${dist_build_desktop}"
fi

set_default_variable dist_binary_build_folder "${binary_build_folder_dist}/${dist_build_version}"

set_default_variable binary_image_raw_file "${dist_binary_build_folder}/${SHORT_VMNAME}-${dist_build_desktop}-${dist_build_version}.${target_architecture_pretty_name}.raw"
set_default_variable binary_image_qcow2_file "${dist_binary_build_folder}/${SHORT_VMNAME}-${dist_build_desktop}-${dist_build_version}.${target_architecture_pretty_name}.qcow2"

for vm_name_item_to_be_exported in $vm_names_to_be_exported ; do
   if printf "%s\n" "$vm_name_item_to_be_exported" | grep --quiet --ignore-case -- "$dist_build_type_long" ; then
      continue
   fi
   set_default_variable binary_image_raw_file_for_unified "${dist_binary_build_folder}/${vm_name_item_to_be_exported}-${dist_build_version}.${target_architecture_pretty_name}.raw"
   set_default_variable binary_image_qcow2_file_for_unified "${dist_binary_build_folder}/${vm_name_item_to_be_exported}-${dist_build_version}.${target_architecture_pretty_name}.qcow2"
done

set_default_variable binary_image_ova_file "${dist_binary_build_folder}/${dist_unified_name}-${dist_build_version}.${target_architecture_pretty_name}.ova"
set_default_variable binary_image_iso_file "${dist_binary_build_folder}/${SHORT_VMNAME}-${dist_build_desktop}-${dist_build_version}.${target_architecture_pretty_name}.iso"
set_default_variable binary_image_windows_installer_file "${dist_binary_build_folder}/${dist_unified_name}-${dist_build_version}.exe"
set_default_variable libvirt_target_raw_xz_archive_file "${dist_binary_build_folder}/${dist_unified_name}-${dist_build_version}.${target_architecture_pretty_name}.raw.libvirt.xz"
set_default_variable libvirt_target_qcow2_xz_archive_file "${dist_binary_build_folder}/${dist_unified_name}-${dist_build_version}.${target_architecture_pretty_name}.qcow2.libvirt.xz"
set_default_variable source_archive_xz_file "${dist_binary_build_folder}/${dist_unified_name}-${dist_build_version}.xz"

set_default_variable binary_image_text "${dist_binary_build_folder}/${SHORT_VMNAME}-${dist_build_desktop}-${dist_build_version}.text"

## virtualbox-installer / dist-installer-cli
set_default_variable binary_image_installer_dist_source "${source_code_folder_dist}/packages/kicksecure/usability-misc/usr/share/usability-misc/dist-installer-cli-standalone"
set_default_variable binary_image_installer_dist_file "${dist_binary_build_folder}/dist-installer-cli"

set_default_variable libvirt_source_kvm_file "${source_code_folder_dist}/packages/kicksecure/libvirt-dist/usr/share/libvirt-dist/xml/${SHORT_VMNAME}.xml"
set_default_variable libvirt_target_kvm_file "${dist_binary_build_folder}/${SHORT_VMNAME}.xml"

set_default_variable source_utm_file "${source_code_folder_dist}/packages/kicksecure/libvirt-dist/usr/share/utm/${SHORT_VMNAME}.plist.template"
set_default_variable binary_image_utm_folder "${dist_binary_build_folder}/${SHORT_VMNAME}-${dist_build_desktop}.utm"

set_default_variable libvirt_source_network_file_external "${source_code_folder_dist}/packages/kicksecure/libvirt-dist/usr/share/libvirt-dist/xml/Whonix-External.xml"
set_default_variable libvirt_target_network_file_external "${dist_binary_build_folder}/Whonix_external_network.xml"

set_default_variable libvirt_source_network_file_internal "${source_code_folder_dist}/packages/kicksecure/libvirt-dist/usr/share/libvirt-dist/xml/Whonix-Internal.xml"
set_default_variable libvirt_target_network_file_internal "${dist_binary_build_folder}/Whonix_internal_network.xml"

# TODO: broken
set_default_variable copy_vms_into_raw_file_one "${dist_binary_build_folder}/Whonix-Gateway-${dist_build_desktop}-${dist_build_version}.qcow2"
set_default_variable copy_vms_into_raw_file_two "${dist_binary_build_folder}/Whonix-Workstation-${dist_build_desktop}-${dist_build_version}.qcow2"

## Sanity test. dm-prepare-release uses 'rm --force --recursive'.
## XXX: hardcoded derivative-binary
if ! printf "%s\n" "$dist_binary_build_folder" | grep --quiet --fixed-strings -- "derivative-binary" ; then
   printf "%s\n" "$0: FAIL: wrong folder: dist_binary_build_folder: $dist_binary_build_folder"
   exit 1
fi

mkdir --parents -- "${dist_binary_build_folder}"

## {{{

## proper whitespace handling
## https://www.whonix.org/wiki/Dev/bash
unset dist_build_files_to_upload
declare -a dist_build_files_to_upload

if [ "$dist_build_virtualbox" = "true" ]; then
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="${ssh_uploader_account}@${dist_server_with_upload_location_list_list}:/var/rsync/ova"

   dist_build_files_to_upload+=("$binary_image_ova_file")
fi

if [ "$dist_build_iso" = "true" ]; then
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="${ssh_uploader_account}@${dist_server_with_upload_location_list_list}:/var/rsync/iso"

   dist_build_files_to_upload+=("$binary_image_iso_file")
fi

if [ "$dist_build_qcow2" = "true" ]; then
   #[ -n "$ssh_uploader_account" ] || ssh_uploader_account="hulahoop"
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="${ssh_uploader_account}@${dist_server_with_upload_location_list_list}:/var/rsync/libvirt"

   dist_build_files_to_upload+=("$libvirt_target_qcow2_xz_archive_file")
fi

if [ "$dist_build_installer_dist" = "true" ]; then
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="
${ssh_uploader_account}@kicksecure.com:/var/rsync/dist-installer-cli
${ssh_uploader_account}@whonix.org:/var/rsync/dist-installer-cli
"

   dist_build_files_to_upload+=("$binary_image_installer_dist_file")
fi

if [ "$dist_build_windows_installer" = "true" ]; then
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="${ssh_uploader_account}@${dist_server_with_upload_location_list_list}:/var/rsync/windows"

   dist_build_files_to_upload+=("$binary_image_windows_installer_file")
fi

if [ "$dist_build_source_archive" = "true" ]; then
   [ -n "$ssh_uploader_account" ] || ssh_uploader_account="root"
   [ -n "$dist_server_with_upload_location_list" ] || dist_server_with_upload_location_list="${ssh_uploader_account}@${dist_server_with_upload_location_list_list}:/var/rsync/source"

   dist_build_files_to_upload+=("$source_archive_xz_file")
fi

## }}}

## {{{ buildconfig.d

[ -n "$dist_build_config_dirs" ] || dist_build_config_dirs="${source_code_folder_dist}/buildconfig.d /etc/buildconfig-dist.d ../buildconfig.d"

dist_build_source_config_dir() {
   true "${cyan}INFO: Checking if dist_build_config_dir $dist_build_config_dir exists...${reset}"
   if [ -d "$1" ]; then
      true "${cyan}INFO: Parsing $1...${reset}"
      shopt -s nullglob
      local i
      for i in "$1/"*".conf"; do
         bash -n "$i"
         source "$i"
      done
   else
      true "${cyan}INFO: Skipping $1 because it does not exist.${reset}"
   fi
}

for dist_build_config_dir in $dist_build_config_dirs; do
   dist_build_source_config_dir "$dist_build_config_dir"
done

if [ ! "$dist_build_custom_config_dir" = "" ]; then
   dist_build_source_config_dir "$dist_build_custom_config_dir"
fi

if [ ! "$dist_build_conf_file" = "" ]; then
   if [ -f "$dist_build_conf_file" ]; then
      bash -n "$dist_build_conf_file"
      source "$dist_build_conf_file"
   fi
fi

## }}}

export make_use_lintian
export genmkfile_make_cmd
export make_use_cowbuilder

[ -n "$gpg_bin" ] || gpg_bin="gpg"
#[ -n "$gpg_bin" ] || gpg_bin="qubes-gpg-client-wrapper"

[ -n "$signify_folder" ] || signify_folder="/home/$user_name/.signify"
[ -n "$signify_private_key" ] || signify_private_key="$signify_folder/keyname.sec"
[ -n "$signify_public_key" ] || signify_public_key="$signify_folder/keyname.pub"

## {{{ fallback variables for debchange (dch), dpkg-buildpackage and debuild

## 'dpkg-source --require-valid-signature' does not support the GNUPGHOME
## environment variable. Hence, hardcoding to the default folder. Otherwise
## genmkfile would break at 'dpkg-source --require-valid-signature'.
[ -n "$dist_local_signing_key_folder" ] || dist_local_signing_key_folder=~/.gnupg
[ -n "$dist_build_reprepro_signing_options" ] || dist_build_reprepro_signing_options="--gnupghome $dist_local_signing_key_folder"
[ -n "$GNUPGHOME" ] ||  GNUPGHOME="$dist_local_signing_key_folder"

## see: man debchange
[ -n "$DEBFULLNAME" ] || DEBFULLNAME="derivative distribution auto generated local APT signing key"
export DEBFULLNAME

[ -n "$DEBEMAIL" ] || DEBEMAIL="derivative-distribution@local-signing.key"
export DEBEMAIL

signing_gpg_key_fingerprint_function() {
   ## Unfortunately there is no simple way to get the fingerprint for a key id (e-mail address)
   ## using gpg command line.
   ## https://unix.stackexchange.com/questions/743982/how-to-use-grep-to-get-the-gpg-key-fingerprint-values
   ## Overwriting with '|| true' because a signing key might not have been created by the time
   ## this script is sourced. Sanity testing is done outside help-steps/variables.
   signing_gpg_key_fingerprint=$(gpg --list-secret-keys --keyid-format 0xlong --with-colons "$DEBEMAIL" 2>/dev/null | awk -F: '$1 == "fpr" || $1 == "fp2" {print $10}' | head -1) || true
}

if [ "$DEBSIGN_KEYID" = "" ]; then
   ## sets: signing_gpg_key_fingerprint
   signing_gpg_key_fingerprint_function
   export DEBSIGN_KEYID="$signing_gpg_key_fingerprint"
fi

## Not a duplicate. Useful for lkrg "dpkg-buildpackage -us -uc -ui -sa" since
## it its debian/changelog file is created by a different author.
export DEB_SIGN_KEYID="$DEBSIGN_KEYID"

export make_debsign_opts="-k$DEBSIGN_KEYID"

## For whatever it may be worth.
## https://forums.whonix.org/t/end-to-end-signed-debs-debsign-debsig-and-dpkg-sig
[ -n "$make_use_debsign" ] || make_use_debsign="true"
export make_use_debsign

## }}}

## {{{ apt repository variables

[ -n "$dist_build_apt_codename" ] || dist_build_apt_codename="local"
export dist_build_apt_codename
## developer local setting in buildconfig.d folder / dist_build_source_config_dir function:
## export dist_build_apt_codename="trixie-developers"

## }}}

## {{{ reprepro variables

set_dist_build_reprepro_folder_options() {
   ## derivative_repository_name gets set by packages/kicksecure/genmkfile/usr/share/genmkfile/make-helper-one.bsh
   true "derivative_repository_name: $derivative_repository_name"
   true "make_reprepro_codename_item: $make_reprepro_codename_item"
   if [ "$derivative_repository_name" = "" ]; then
      error "derivative_repository_name is empty!"
   fi

   for derivative_name_item in $derivative_name_list ; do
      if [ "$derivative_repository_name" = "$derivative_name_item" ]; then
         valid_repository_name=true
         break
      fi
   done

   if [ ! "$valid_repository_name" = "true" ]; then
      error "derivative_repository_name '$derivative_repository_name' is invalid! (not in derivative_name_list)"
   fi

   [[ -v make_reprepro_codename_item ]] || make_reprepro_codename_item="$dist_build_apt_codename"

   if [ ! "$make_reprepro_codename_item" = "local" ]; then
      apt_repo_sub_folder="aptrepo_remote/$derivative_repository_name"
   else
      apt_repo_sub_folder="aptrepo_local/$derivative_repository_name"
   fi

   dist_apt_repository_folder="$binary_build_folder_dist/$apt_repo_sub_folder"
   export dist_apt_repository_folder

   dist_build_reprepro_folder_options="\
      --basedir ${source_code_folder_dist}/$apt_repo_sub_folder \
      --outdir $binary_build_folder_dist/$apt_repo_sub_folder \
      --dbdir $binary_build_folder_dist/$apt_repo_sub_folder/db \
      --logdir $binary_build_folder_dist/$apt_repo_sub_folder/log"
   export dist_build_reprepro_folder_options
}

## }}}

[ -n "$host_architecture" ] || host_architecture="$(dpkg --print-architecture)"
export host_architecture

[ -n "$make_cross_build_platform_list" ] || make_cross_build_platform_list="$dist_build_target_arch"
#[ -n "$make_cross_build_platform_list" ] || make_cross_build_platform_list="i386 amd64"
export make_cross_build_platform_list

set_cowbuilder_folders() {
   ## TODO: change that folder
   cow_folder="/var/cache/pbuilder/cow.cow_${dist_build_multiarch_package_item}"
   base_folder="/var/cache/pbuilder/base.cow_${dist_build_multiarch_package_item}"
}

[ -n "$dist_build_file_system" ] || dist_build_file_system="ext4"

## cowbuilder (which internally uses pbuilder).
dist_build_pbuilder_main_chroot_script="$dist_source_help_steps_folder/pbuilder-chroot-script-main"
dist_build_pbuilder_virtualbox_chroot_script="$dist_source_help_steps_folder/pbuilder-chroot-script-virtualbox"

dist_build_pbuilder_config_file="$binary_build_folder_dist/pbuilder.conf"
## export so it can be read by genmkfile
export dist_build_pbuilder_config_file

make_cowbuilder_dist_folder="$binary_build_folder_dist/genmkfile-packages-result"
export make_cowbuilder_dist_folder

$SUDO_TO_ROOT rm --force -- "$dist_build_pbuilder_config_file"
mkdir --parents -- "$binary_build_folder_dist"
mkdir --parents -- "$make_cowbuilder_dist_folder"

printf "%s\n" "\
## This is an auto generated file.
## Auto generated by: '$dist_source_help_steps_folder/$BASH_SOURCE'
## Edits will be lost!

## build-step cowbuilder-setup copies this file into cowbuilder chroot to:
## '/home/$user_name/pbuilder_config_file'

## dist_build_pbuilder_config_file is passed to cowbuilder. example:
## '--configfile /home/user/derivative-binary/pbuilder.conf'
## NOTE: Cowbuilder ignores arbitrary environment variables such as 'APTGETOPT_SERIALIZED'.
##       Therefore, cowbuilder chroot scripts must run:
##       'source /home/$user_name/pbuilder_config_file'
##       Maybe false. Just requires correct 'export'.

## Debugging.
#set -x

## making pbuilder /usr/lib/pbuilder/pbuilder-createbuildenv work with mmdebstrap.
## so it can be read by help-steps/mmdebstrap wrapper
export BUILDPLACE

APTCACHEHARDLINK=no
export APTCACHEHARDLINK

## E: Cross building is possible only with the APT dependency resolver
## Not compatible with 'set -o nounset'.
PBUILDERSATISFYDEPENDSCMD=/usr/lib/pbuilder/pbuilder-satisfydepends-apt
export PBUILDERSATISFYDEPENDSCMD

## End of: '$dist_build_pbuilder_config_file'
" | \
   tee -- "$dist_build_pbuilder_config_file" >/dev/null

#realpath -- "$dist_build_pbuilder_config_file"
#cat -- "$dist_build_pbuilder_config_file"

## Under non-Qubes, resolv.conf is bind-mounted from the host and must not be
## changed for tb-updater to be able to download Tor Browser successfully.
##
## Under Qubes, resolv.conf is provided as part of the template and is
## overridden by Whonix's network config, so resolv.conf.whonix-orig needs to
## be moved back to resolv.conf temporarily to be able to download Tor Browser
## successfully.
##
## Therefore, set tb_disable_anon_ws_dns_conf to false so that
## derivative-maker Whonix builds can download Tor Browser. Qubes builds will
## have this variable set to true, and will therefore also be able to download
## Tor Browser.
tb_disable_anon_ws_dns_conf=false
export tb_disable_anon_ws_dns_conf

## {{{ SKIP_SCRIPTS

## Would be nicer to have this in the 'pre' script, but the 'variables' script
## runs after 'pre' to provide pretty color functions.
own_filename="$(basename -- "$0")"
for skip_script in $SKIP_SCRIPTS; do
   if matched_word=$(printf "%s\n" "$own_filename" | grep -- "$skip_script") ; then
      unset skip_script
      printf "%s\n" "${bold}${green}$BASH_SOURCE INFO: Skipping $own_filename, because SKIP_SCRIPTS matches it. matched_word: '$matched_word'${reset}"
      exit 0
   fi
done
unset skip_script

## }}}

true "INFO: LD_PRELOAD: $LD_PRELOAD"

env_vars_keep_list="
   APTGETOPT_SERIALIZED
   tbb_version
   tb_onion
   tpo_downloader_debug
   tb_disable_anon_ws_dns_conf
   anon_shared_inst_tb
   CURL_PROXY
   SKIP_SCRIPTS
   SOURCE_DATE_EPOCH
   dist_aptgetopt_file
   dist_build_sources_list_primary
   dist_mmdebstrap_build_sources_list_primary
   dist_build_sources_list_primary_contents
   dist_build_apt_sources_mirror
   dist_build_apt_stable_release
   dist_build_target_arch
   dist_grml_mount_point
   dist_source_help_steps_folder
   dist_build_multiarch_package_item
   dist_build_unsafe_io
   dist_build_version
   derivative_maker
   user_name
   LD_PRELOAD
   LC_ALL
   TZ
   DEBDEBUG
   XZ_OPT
   REPO_PROXY
   apt_unattended_opts
   DERIVATIVE_APT_REPOSITORY_OPTS
   DEBOOTSTRAP
   http_proxy
   https_proxy
   ALL_PROXY
   DEBIAN_FRONTEND DEBIAN_PRIORITY DEBCONF_NOWARNINGS APT_LISTCHANGES_FRONTEND
   INITRD
   HOMEVAR_VBOX_TEMP
"
## TODO:
## UWT_DEV_PASSTHROUGH

true "INFO: Environment variables that will be passed..."

for env_vars_var_keep_item in $env_vars_keep_list ; do
   if [ "$sudo_preserve_env_list" = "" ]; then
      sudo_preserve_env_list="$env_vars_var_keep_item"
   else
      sudo_preserve_env_list+=",$env_vars_var_keep_item"
   fi
done

SUDO_TO_ROOT+=" "
SUDO_TO_ROOT+="--preserve-env=$sudo_preserve_env_list"

## XXX: Not possible because some scripts use extra sudo arguments such as "--preserve-env".
#SUDO_TO_ROOT+=" "
#SUDO_TO_ROOT+="--"

#printf "%s\n" "INFO: SUDO_TO_ROOT:"
#printf "%s\n" "${cyan}$SUDO_TO_ROOT${reset}"

## Development.
#set -x
#declare -p | awk '{print $3}' | sort > ~/varnames
#exit

if [ "$xtrace_was_set" = "true" ]; then
   printf "%s\n" "$BASH_SOURCE INFO: xtrace_was_set=true - Therefore re-enable xtrace. (set -x)"
   set -x
fi
true "$BASH_SOURCE INFO: End of script, ok."
