V8.13.064.2025.10.07

Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
2025-10-07 12:51:05 +01:00
parent 181b73b04c
commit 68c803550b
50 changed files with 273 additions and 110 deletions

View File

@@ -13,7 +13,7 @@
guard_sourcing
#######################################
# Argument Parser
# Argument Parser.
# Globals:
# ARY_HANDLER_JUMPHOST
# ARY_HANDLER_NETCUP_IPV6

View File

@@ -44,7 +44,7 @@ cdi() {
tmp_entry="$(mktemp)"
cat << EOF >| "${tmp_entry}"
menuentry "CISS Hardened DI (${VAR_KERNEL})" --hotkey=i {
linux /live/vmlinuz-${VAR_KERNEL} boot=live verify-checksums live-config.components splash nopersistence toram ramdisk-size=1024M swap=true noeject locales=en_US.UTF-8 keyboard-layouts=de keyboard-model=pc105 keyboard-options= keyboard-variants= timezone=Etc/UTC audit_backlog_limit=8192 audit=1 cfi=kcfi debugfs=off efi=disable_early_pci_dma efi_no_storage_paranoia hardened_usercopy=1 ia32_emulation=0 init_on_alloc=1 init_on_free=1 iommu=force kfence.sample_interval=100 kvm.nx_huge_pages=force l1d_flush=on lockdown=confidentiality loglevel=0 mce=0 mitigations=auto,nosmt mmio_stale_data=full,nosmt oops=panic page_alloc.shuffle=1 page_poison=1 panic=-1 pti=on random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on randomize_va_space=2 retbleed=auto,nosmt rodata=on tsx=off vdso32=0 vsyscall=none findiso=\${iso_path}
linux /live/vmlinuz-${VAR_KERNEL} boot=live verify-checksums live-config.components splash nopersistence toram ramdisk-size=1024M swap=true noeject locales=en_US.UTF-8 keyboard-layouts=de keyboard-model=pc105 keyboard-options= keyboard-variants= timezone=Etc/UTC audit_backlog_limit=8192 audit=1 cfi=kcfi debugfs=off efi=disable_early_pci_dma hardened_usercopy=1 ia32_emulation=0 init_on_alloc=1 init_on_free=1 iommu.passthrough=0 iommu.strict=1 iommu=force kfence.sample_interval=100 kvm.nx_huge_pages=force l1d_flush=on lockdown=confidentiality loglevel=0 mitigations=auto,nosmt mmio_stale_data=full,force nosmt=force oops=panic page_alloc.shuffle=1 page_poison=1 panic=0 pti=on random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on randomize_va_space=2 retbleed=auto,nosmt rodata=on slab_nomerge vdso32=0 vsyscall=none findiso=\${iso_path}
initrd /live/initrd.img-${VAR_KERNEL}
}
EOF

View File

@@ -72,6 +72,11 @@ check_pkgs() {
fi
# shellcheck disable=SC2034,SC2155
declare -gr VAR_LB_VER="$(lb -v)"
# shellcheck disable=SC2034,SC2155
declare -gr VAR_DS_VER="$(debootstrap --version)"
return 0
}
### Prevents accidental 'unset -f'.

View File

@@ -22,7 +22,9 @@ guard_sourcing
# VAR_VERSION
# VAR_WORKDIR
# Arguments:
# None
# None
# Returns:
# 0: on success
#######################################
lb_config_write_trixie() {
printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 Writing new config ... \e[0m\n"
@@ -39,7 +41,7 @@ lb_config_write_trixie() {
--binary-filesystem fat32 \
--binary-image iso-hybrid \
--bootappend-install "auto=true priority=critical clock-setup/utc=true console-setup/ask_detect=false debian-installer/country=US debian-installer/language=en debian-installer/locale=en_US.UTF-8 keyboard-configuration/xkb-keymap=de keyboard-configuration/model=pc105 localechooser/supported-locales=en_US.UTF-8 time/zone=Etc/UTC splash audit_backlog_limit=8192 audit=1 cfi=kcfi debugfs=off efi=disable_early_pci_dma efi_no_storage_paranoia hardened_usercopy=1 ia32_emulation=0 init_on_alloc=1 init_on_free=1 iommu=force kfence.sample_interval=100 kvm.nx_huge_pages=force l1d_flush=on lockdown=confidentiality loglevel=0 mce=0 mitigations=auto,nosmt mmio_stale_data=full,nosmt oops=panic page_alloc.shuffle=1 page_poison=1 panic=-1 pti=on random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on randomize_va_space=2 retbleed=auto,nosmt rodata=on tsx=off vdso32=0 vsyscall=none" \
--bootappend-live "boot=live components keyboard-layouts=de keyboard-model=pc105 keyboard-options= keyboard-variants= locales=en_US.UTF-8 noeject nopersistence ramdisk-size=1024M splash swap=true timezone=Etc/UTC toram verify-checksums audit_backlog_limit=8192 audit=1 cfi=kcfi debugfs=off efi=disable_early_pci_dma hardened_usercopy=1 ia32_emulation=0 init_on_alloc=1 init_on_free=1 iommu.passthrough=0 iommu.strict=1 iommu=force kfence.sample_interval=100 kvm.nx_huge_pages=force l1d_flush=on lockdown=confidentiality loglevel=0 mitigations=auto,nosmt mmio_stale_data=full,force,nosmt nosmt=force oops=panic page_alloc.shuffle=1 page_poison=1 panic=-1 pti=on random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on randomize_va_space=2 retbleed=auto,nosmt rodata=on slab_nomerge vdso32=0 vsyscall=none" \
--bootappend-live "boot=live components keyboard-layouts=de keyboard-model=pc105 keyboard-options= keyboard-variants= locales=en_US.UTF-8 noeject nopersistence ramdisk-size=1024M splash swap=true timezone=Etc/UTC toram verify-checksums audit_backlog_limit=8192 audit=1 cfi=kcfi debugfs=off efi=disable_early_pci_dma hardened_usercopy=1 ia32_emulation=0 init_on_alloc=1 init_on_free=1 iommu.passthrough=0 iommu.strict=1 iommu=force kfence.sample_interval=100 kvm.nx_huge_pages=force l1d_flush=on lockdown=confidentiality loglevel=0 mitigations=auto,nosmt mmio_stale_data=full,force nosmt=force oops=panic page_alloc.shuffle=1 page_poison=1 panic=0 pti=on random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on randomize_va_space=2 retbleed=auto,nosmt rodata=on slab_nomerge vdso32=0 vsyscall=none" \
--bootloaders grub-efi \
--cache true \
--checksums sha512 sha256 md5 \
@@ -111,5 +113,10 @@ lb_config_write_trixie() {
chown root:root "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/usr/lib/live/boot/0030-verify-checksums"
printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ Writing new config done.\e[0m\n"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f lb_config_write_trixie
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

61
lib/lib_note_target.sh Normal file
View File

@@ -0,0 +1,61 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-10-07; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
#######################################
# Version file generator for '/root/cdlb.txt' of Live ISO.
# Globals:
# VAR_VERSION
# Arguments:
# None
# Returns:
# 0: on success
#######################################
note_target() {
cat << EOF >| "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/cdlb.txt"
################################################################################
This CISS.debian.live ISO was built by:
CISS.debian.live.builder from https://git.coresecret.dev/msw
A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
Version : ${VAR_VERSION}
Git : ${VAR_GIT_REL}
Date : ${VAR_DATE_INFO}
Host : ${VAR_HOST}
Bash : ${VAR_BASH_VER}
Debootstrap : ${VAR_DS_VER}
Live-Build : ${VAR_LB_VER}
This program is free software. Distribution and modification under
EUPL-1.2 permitted. USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!
Please file bugs @
https://git.coresecret.dev/msw/CISS.debian.live.builder/issues
Contact
https://coresecret.eu/
security@coresecret.eu
PGP Key 2D98 07F4 1030 1776 597E BDC9 9F54 8853 35A3 C9AD
https://keys.openpgp.org/vks/v1/by-fingerprint/2D9807F410301776597EBDC99F54885335A3C9AD
Please consider donating to my work at:
https://coresecret.eu/spenden/
################################################################################
EOF
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f note_target
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -15,15 +15,18 @@ guard_sourcing
#######################################
# Wrapper for statistic functions of the final build.
# Globals:
# ERR_UNCRITICAL
# VAR_BUILD_LOG
# VAR_CHROOT_DIR
# VAR_HANDLER_BUILD_DIR
# VAR_PACKAGES_FILE
# Arguments:
# None
# None
# Returns:
# 0: on success
# ERR_UNCRITICAL: on failure
#######################################
run_analysis() {
clear
# shellcheck disable=SC2164
cd "${VAR_HANDLER_BUILD_DIR}"
# shellcheck disable=SC2155
@@ -51,12 +54,14 @@ run_analysis() {
declare squash_cpu_used="$(grep -m1 -oP 'Using \K[0-9]+' "${VAR_BUILD_LOG}")"
if [[ -f "${VAR_BUILD_LOG}" ]]; then
# shellcheck disable=SC2155
declare start_line=$(grep 'lb build' "${VAR_BUILD_LOG}" | head -n1 || true)
# shellcheck disable=SC2155
declare end_line=$(grep 'lb source' "${VAR_BUILD_LOG}" | tail -n1 || true)
if [[ -n "${start_line}" && -n "${end_line}" ]]; then
# shellcheck disable=SC2155
declare start_epoch=$(echo "${start_line}" | sed -E 's/^\[([0-9:-]+ [0-9:]+)\].*/\1/' | xargs -I{} date -d "{}" +%s)
# shellcheck disable=SC2155
@@ -69,15 +74,21 @@ run_analysis() {
declare duration_rest=$((duration_sec % 60))
# shellcheck disable=SC2155
declare build_duration=$(printf "%02dm:%02ds" "${duration_min}" "${duration_rest}")
else
declare build_duration="(Timestamp not found)"
fi
else
declare build_duration="(No log file found)"
fi
# shellcheck disable=SC2155
declare sha_sum=$(sha256sum "$iso_file" | tee "$iso_file.sha256" | awk '{print $1}')
declare sha_sum=$(sha256sum "${iso_file}" | tee "${iso_file}.sha256" | awk '{print $1}')
# shellcheck disable=SC2155
declare time=$(date '+%Y-%m-%d %H:%M:%S')
@@ -94,5 +105,10 @@ run_analysis() {
printf "\e[92m----------------------------------------------------------------------------------------\e[0m\n"
printf "\e[97m📅 Analysis Time : %s \e[0m\n" "${time}"
printf "\e[92m✅ Analysis completed.\e[0m\n"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f run_analysis
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -15,23 +15,27 @@ guard_sourcing
#######################################
# Print Error Message for Trap on 'ERR' in ${ERROR_LOG}
# Globals:
# VAR_PARAM_COUNT
# VAR_PARAM_STRNG
# VAR_ARG_SANITIZED
# LOG_DEBUG
# ERRCMMD
# ERRCODE
# ERRFUNC
# ERRLINE
# ERRSCRT
# LOG_DEBUG
# LOG_ERROR
# LOG_VAR
# SECONDS
# VAR_ARG_SANITIZED
# VAR_BASH_VER
# VAR_DS_VER
# VAR_EARLY_DEBUG
# VAR_GIT_REL
# VAR_LB_VER
# VAR_PARAM_COUNT
# VAR_PARAM_STRNG
# VAR_SYSTEM
# VAR_VERSION
# Arguments:
# None
# None
#######################################
print_file_err() {
{
@@ -39,6 +43,9 @@ print_file_err() {
printf "❌ Git Commit : %s \n" "${VAR_GIT_REL}"
printf "❌ Version : %s \n" "${VAR_VERSION}"
printf "❌ Hostsystem : %s \n" "${VAR_SYSTEM}"
printf "❌ Bash : %s \n" "${VAR_BASH_VER}"
printf "❌ Live-Build : %s \n" "${VAR_LB_VER}"
printf "❌ Debootstrap : %s \n" "${VAR_DS_VER}"
printf "❌ Error : %s \n" "${ERRCODE}"
printf "❌ Line : %s \n" "${ERRLINE}"
printf "❌ Script : %s \n" "${ERRSCRT}"
@@ -48,41 +55,55 @@ print_file_err() {
printf "❌ Arguments Counter : %s \n" "${VAR_PARAM_COUNT}"
printf "❌ Arguments Original : %s \n" "${VAR_PARAM_STRNG}"
printf "❌ Arguments Sanitized : %s \n" "${VAR_ARG_SANITIZED}"
if "${VAR_EARLY_DEBUG}"; then
printf "❌ Vars Dump saved at : %s \n" "${LOG_VAR}"
printf "❌ Debug Log saved at : %s \n" "${LOG_DEBUG}"
printf "❌ batcat --pager='less -r' %s \n" "${LOG_DEBUG}"
fi
printf "\n"
} >> "${LOG_ERROR}"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f print_file_err
#######################################
# Print Error Message for Trap on 'ERR' on Terminal
# Globals:
# VAR_PARAM_COUNT
# VAR_PARAM_STRNG
# VAR_ARG_SANITIZED
# LOG_DEBUG
# ERRCMMD
# ERRCODE
# ERRFUNC
# ERRLINE
# ERRSCRT
# LOG_DEBUG
# LOG_ERROR
# LOG_VAR
# SECONDS
# VAR_ARG_SANITIZED
# VAR_BASH_VER
# VAR_DS_VER
# VAR_EARLY_DEBUG
# VAR_GIT_REL
# VAR_LB_VER
# VAR_PARAM_COUNT
# VAR_PARAM_STRNG
# VAR_SYSTEM
# VAR_VERSION
# Arguments:
# None
# None
#######################################
print_scr_err() {
printf "\e[91m❌ CISS.debian.live.builder Script failed. \e[0m\n" >&2
printf "\e[91m❌ Git Commit : %s \e[0m\n" "${VAR_GIT_REL}" >&2
printf "\e[91m❌ Version : %s \e[0m\n" "${VAR_VERSION}" >&2
printf "\e[91m❌ Hostsystem : %s \e[0m\n" "${VAR_SYSTEM}" >&2
printf "\e[91m❌ Bash : %s \e[0m\n" "${VAR_BASH_VER}" >&2
printf "\e[91m❌ Live-Build : %s \e[0m\n" "${VAR_LB_VER}" >&2
printf "\e[91m❌ Debootstrap : %s \e[0m\n" "${VAR_DS_VER}" >&2
printf "\e[91m❌ Error : %s \e[0m\n" "${ERRCODE}" >&2
printf "\e[91m❌ Line : %s \e[0m\n" "${ERRLINE}" >&2
printf "\e[91m❌ Script : %s \e[0m\n" "${ERRSCRT}" >&2
@@ -94,13 +115,20 @@ print_scr_err() {
printf "\e[91m❌ Arguments Sanitized : %s \e[0m\n" "${VAR_ARG_SANITIZED}" >&2
printf "\e[91m❌ Error Log saved at : %s \e[0m\n" "${LOG_ERROR}" >&2
printf "\e[91m❌ batcat --pager='less -r' %s \e[0m\n" "${LOG_ERROR}" >&2
if "${VAR_EARLY_DEBUG}"; then
printf "\e[91m❌ Vars Dump saved at : %s \e[0m\n" "${LOG_VAR}" >&2
printf "\e[91m❌ Debug Log saved at : %s \e[0m\n" "${LOG_DEBUG}" >&2
printf "\e[91m❌ batcat --pager='less -r' %s \e[0m\n" "${LOG_DEBUG}" >&2
fi
printf "\n"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f print_scr_err
#######################################
# Trap function to be called on 'ERR'.
@@ -112,14 +140,15 @@ print_scr_err() {
# ERRSCRT
# VAR_EARLY_DEBUG
# Arguments:
# $1: $?
# $2: ${BASH_SOURCE[0]}
# $3: ${LINENO}
# $4: ${FUNCNAME[0]:-main}
# $5: ${BASH_COMMAND}
# 1: $?
# 2: ${BASH_SOURCE[0]}
# 3: ${LINENO}
# 4: ${FUNCNAME[0]:-main}
# 5: ${BASH_COMMAND}
#######################################
trap_on_err() {
trap - DEBUG ERR INT TERM
declare -g ERRCODE="$1"
declare -g ERRSCRT="$2"
declare -g ERRLINE="$3"
@@ -129,11 +158,18 @@ trap_on_err() {
declare -g ERRTRAP="true"
if "${VAR_EARLY_DEBUG}"; then dump_user_vars; fi
clean_up "${ERRCODE}"
if ! "${VAR_HANDLER_AUTOBUILD}"; then clean_screen; fi
print_file_err
print_scr_err
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f trap_on_err
#######################################
# Gather all user-defined variables (name and value)
@@ -142,7 +178,7 @@ trap_on_err() {
# VAR_DUMP_VARS_INITIAL
# VAR_VERSION
# Arguments:
# None
# None
#######################################
dump_user_vars() {
### Capture the final snapshot of all variables (excluding '^(BASH|_).*')
@@ -175,4 +211,7 @@ dump_user_vars() {
comm -13 "${VAR_DUMP_VARS_INITIAL}" "${dump_vars_final}" >> "${LOG_VAR}" || true
rm "${VAR_DUMP_VARS_INITIAL}" "${dump_vars_final}"
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f dump_user_vars
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -17,20 +17,32 @@ guard_sourcing
# Globals:
# VAR_EARLY_DEBUG
# Arguments:
# $1: $?
# 1: $?
#######################################
trap_on_exit() {
trap - DEBUG ERR EXIT INT TERM
declare -r var_trap_on_exit_code="$1"
if (( var_trap_on_exit_code == 0 )); then
if "${VAR_EARLY_DEBUG}"; then dump_user_vars; fi
clean_up "${var_trap_on_exit_code}"
print_scr_exit "${var_trap_on_exit_code}"
exit "${var_trap_on_exit_code}"
else
exit "${var_trap_on_exit_code}"
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f trap_on_exit
#######################################
# Print Success Message for Trap on 'EXIT' on 'stdout'.
@@ -38,32 +50,56 @@ trap_on_exit() {
# LOG_DEBUG
# LOG_VAR
# SECONDS
# VAR_BASH_VER
# VAR_DS_VER
# VAR_EARLY_DEBUG
# VAR_GIT_REL
# VAR_HANDLER_BUILD_DIR
# VAR_LB_VER
# VAR_SCRIPT_SUCCESS
# VAR_SYSTEM
# VAR_VERSION
# Arguments:
# $1: ${var_trap_on_exit_code} of trap_on_exit()
# 1: ${var_trap_on_exit_code} of trap_on_exit()
#######################################
print_scr_exit() {
declare -r var_print_scr_exit_code="$1"
if (( var_print_scr_exit_code == 0 )); then
if [[ "${VAR_SCRIPT_SUCCESS}" == "true" ]]; then
printf "\n"
printf "\e[92m✅ CISS.debian.live.builder Script successful. \e[0m\n"
printf "\e[92m✅ CISS.debian.live.builder Script successfully completed. \e[0m\n"
printf "\e[92m✅ Git Commit : %s \e[0m\n" "${VAR_GIT_REL}"
printf "\e[92m✅ Version : %s \e[0m\n" "${VAR_VERSION}"
printf "\e[92m✅ Hostsystem : %s \e[0m\n" "${VAR_SYSTEM}"
printf "\e[92m✅ Bash : %s \e[0m\n" "${VAR_BASH_VER}"
printf "\e[92m✅ Live-Build : %s \e[0m\n" "${VAR_LB_VER}"
printf "\e[92m✅ Debootstrap : %s \e[0m\n" "${VAR_DS_VER}"
printf "\e[92m✅ Aide Initial DB at : %s \e[0m\n" "${VAR_HANDLER_BUILD_DIR}/.integrity/"
printf "\e[92m✅ Exited with Status : %s \e[0m\n" "${var_print_scr_exit_code}"
printf "\n"
if [[ "${VAR_EARLY_DEBUG}" == "true" ]]; then
printf "\e[92m✅ Script Runtime : %s \e[0m\n" "${SECONDS}"
printf "\e[92m✅ Vars Dump saved at : %s \e[0m\n" "${LOG_VAR}"
printf "\e[92m✅ Debug Log saved at : %s \e[0m\n" "${LOG_DEBUG}"
printf "\e[92m✅ batcat --pager='less -r' %s \e[0m\n" "${LOG_DEBUG}"
printf "\n"
fi
printf "\e[95m💷 Please consider donating to my work at: \e[0m\n"
printf "\e[95m🔗 https://coresecret.eu/spenden/ \e[0m\n"
printf "\n"
fi
fi
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f print_scr_exit
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh

View File

@@ -13,7 +13,7 @@
#######################################
# Usage Wrapper CISS.debian.live.builder
# Arguments:
# $0: Script name
# 0: Script name
#######################################
usage() {
# shellcheck disable=SC2155
@@ -22,8 +22,8 @@ usage() {
#######################################
# Header, Footer wrapper for dynamical output.
# Arguments:
# $1: Text.
# $2: Width of Terminal.
# 1: Text.
# 2: Width of Terminal.
#######################################
center() {
declare var_text="$1"
@@ -35,13 +35,13 @@ usage() {
# shellcheck disable=SC2155
declare var_header=$(center "CLB(1) CISS.debian.live.builder CLB(1)" "${var_cols}")
# shellcheck disable=SC2155
declare var_footer=$(center "V8.13.048.2025.10.06 2025-08-11 CLB(1)" "${var_cols}")
declare var_footer=$(center "V8.13.064.2025.10.07 2025-10-07 CLB(1)" "${var_cols}")
{
echo -e "\e[1;97m${var_header}\e[0m"
echo
echo -e "\e[92mCISS.debian.live.builder from https://git.coresecret.dev/msw \e[0m"
echo -e "\e[92mMaster V8.13.048.2025.10.06\e[0m"
echo -e "\e[92mMaster V8.13.064.2025.10.07\e[0m"
echo -e "\e[92mA lightweight Shell Wrapper for building a hardened Debian Live ISO Image.\e[0m"
echo
echo -e "\e[97m(c) Marc S. Weidner, 2018 - 2025 \e[0m"