Files
Tools/list_root_domains.sh
HRiggs e0d1a9193f
Some checks failed
Generate README / build (push) Failing after 21s
New tools and deploy
2025-09-28 17:09:17 -04:00

82 lines
2.1 KiB
Bash

#!/bin/sh
set -eu
# Print a comma-separated list of unique registrable root domains (eTLD+1)
# for non-suspended cPanel users based on /etc/userdomains.
#
# Tries to use `psl` (libpsl) if available for correct public suffix handling.
# Falls back to a heuristic for common multi-level TLDs if `psl` is unavailable.
USERDOMAINS_PATH="/etc/userdomains"
SUSPENDED_DIR="/var/cpanel/suspended"
error() {
printf "Error: %s\n" "$*" 1>&2
}
have_psl() {
command -v psl >/dev/null 2>&1
}
get_root_domain() {
# Derive registrable domain (eTLD+1) from a hostname
# 1) Prefer libpsl via `psl --print`
# 2) Fallback heuristic for common multi-level TLDs
hostname="$1"
# strip trailing dot if any
case "$hostname" in
*.) hostname=${hostname%\.} ;;
esac
if have_psl; then
printed=$(psl --print "$hostname" 2>/dev/null | tr -d '\r')
if [ -n "$printed" ]; then
printf "%s\n" "$printed"
return 0
fi
fi
# Fallback heuristic implemented in awk to avoid bashisms
printf "%s\n" "$hostname" | awk '
BEGIN { FS = "." }
{
n = NF
if (n >= 3) {
lastTwo = $(n-1) "." $n
if (lastTwo ~ /^(co\.uk|org\.uk|ac\.uk|gov\.uk|ltd\.uk|plc\.uk|me\.uk|co\.jp|ne\.jp|or\.jp|go\.jp|ac\.jp|ed\.jp|gr\.jp|com\.au|net\.au|org\.au|edu\.au|gov\.au|id\.au|asn\.au|com\.br|com\.cn|net\.cn|org\.cn|com\.sg|com\.my|co\.nz)$/) {
print $(n-2) "." lastTwo
next
}
}
if (n >= 2) {
print $(n-1) "." $n
} else {
print $0
}
}'
}
main() {
if [ ! -r "${USERDOMAINS_PATH}" ]; then
error "Cannot read ${USERDOMAINS_PATH}"
exit 1
fi
# Read, normalize whitespace removal like original, skip lines starting with '*'
# Format is typically: domain: user
# For each non-suspended user, emit root domain; then unique-sort and join with commas
sed -e 's/[[:space:]]*//g' -e '/^\*/d' "${USERDOMAINS_PATH}" \
| awk -F: 'NF>=2 { print $1 ":" $2 }' \
| while IFS=":" read -r domain username; do
if [ ! -f "${SUSPENDED_DIR}/${username}" ]; then
get_root_domain "${domain}"
fi
done \
| sort -u \
| paste -sd, -
}
main "$@"