82 lines
2.1 KiB
Bash
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 "$@"
|
|
|
|
|