#!/bin/bash
#
# Change the hostname of the machine.

# Exit on unset variable.
set -u

# Exit on first error.
set -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
readonly SCRIPT_DIR
# shellcheck source=lib/markers.sh
. "${SCRIPT_DIR}/lib/markers.sh"

readonly VALID_HOSTNAME_PATTERN='^[-0-9A-Za-z]+$'

print_help() {
  cat << EOF
Usage: ${0##*/} [-h] new_hostname
Change the hostname of this machine.
  -h Display this help and exit.
EOF
}

# Parse command-line arguments.
while getopts 'h' opt; do
  case "${opt}" in
    h)
      print_help
      exit
      ;;
    *)
      print_help >&2
      exit 1
  esac
done

# Ensure 'new_hostname' is given.
shift $((OPTIND - 1))
if (( $# == 0 )); then
  echo 'Input parameter missing: new_hostname' >&2
  exit 1
fi

# Validate 'new_hostname' parameter.
# See here for the rules:
# https://man7.org/linux/man-pages/man7/hostname.7.html
readonly NEW_HOSTNAME="$1"
if ! [[ "${NEW_HOSTNAME}" =~ $VALID_HOSTNAME_PATTERN ]] \
  || [[ "${NEW_HOSTNAME}" == -* ]] \
  || [[ "${NEW_HOSTNAME}" == 'localhost' ]] \
  || (( ${#NEW_HOSTNAME} > 63 )) \
  ; then
  echo 'Invalid hostname' >&2
  exit 1
fi

# Remove any existing marker sections from the `/etc/hosts` file.
"${SCRIPT_DIR}/strip-marker-sections" /etc/hosts

# Populate new entry to `/etc/hosts`.
# Note that the first matching entry takes precedence, which is why we prepend
# our new entry.
OLD_ETC_HOSTS="$(</etc/hosts)"
readonly OLD_ETC_HOSTS
printf "%s\n127.0.1.1 %s\n%s\n%s\n" \
  "${MARKER_START}" "${NEW_HOSTNAME}" "${MARKER_END}" "${OLD_ETC_HOSTS}" \
  > /etc/hosts

# We use `hostnamectl set-hostname xyz` instead of `hostnamectl hostname xyz`
# because `set-hostname` is backwards compatible with the Bullseye version of
# `hostnamectl`. `hostnamectl hostname xyz` is only supported on the Bookworm
# version.
hostnamectl set-hostname "${NEW_HOSTNAME}"

# On next boot, update the TLS certificate to match the new hostname.
systemctl enable update-tls-cert-common-name
