#!/bin/sh
# SummaPack, Diego Saravia y colaboradores.
# GPL, o cualquier licencia libre con copyleft, como la version original.
# Identifica el sistema/familia de paquetes; no garantiza compatibilidad ABI.
ayuda() {
    cat <<'FIN'
Uso: distro [+]
     distro --help | --version

Sin argumentos: identificador de sistema/familia (UBUNTU, DEBIAN, FEDORA,
REDHAT, SUSE, ARCH, GENTOO, UTUTO, ALPINE, ...).
Con +: agrega nombre y numero de version, por ejemplo UBUNTU_noble_24_04.
Linux: ID de /etc/os-release, luego ID_LIKE en su orden; si falta ese
archivo, /usr/lib/os-release. No mezcla ambos ni los ejecuta.
Sin identificacion moderna usa lsb-release y archivos historicos.
WSL informa su distribucion, no supone Ubuntu.
Linux desconocido: OTHERGNULINUX; otro sistema desconocido: UNKNOWN.
DISTRO_ROOT=/ruta permite leer otra raiz para diagnostico y pruebas;
el kernel sigue siendo el de uname. No es un chroot.
FIN
}
if [ "$#" -gt 1 ]; then
    echo 'distro: se admite un solo argumento (+, --help o --version)' >&2
    exit 2
fi
case "${1-}" in
    '') detalle=0 ;;
    +) detalle=1 ;;
    -h|--help) ayuda; exit 0 ;;
    --version) echo 'distro.sh version 4'; exit 0 ;;
    *) echo "distro: opcion desconocida: $1 (ver --help)" >&2; exit 2 ;;
esac
LC_ALL=C
export LC_ALL
set -f
raiz=${DISTRO_ROOT:-/}
case "$raiz" in
    /*) ;;
    *) echo 'distro: DISTRO_ROOT debe ser absoluta' >&2; exit 2 ;;
esac
[ -d "$raiz" ] || { echo 'distro: DISTRO_ROOT no existe' >&2; exit 2; }
raiz=${raiz%/}

# Solo datos: nunca source/eval. Ultima clave repetida gana.
campo() {
    [ -f "$1" ] && [ -r "$1" ] || return 0
    awk -v clave="$2" '
        {
            sub(/\r$/, "")
            if (index($0, clave "=") != 1) next
            v = substr($0, length(clave) + 2)
            sub(/[ \t]+$/, "", v)
            q = substr(v, 1, 1)
            if (q == "\"" || q == sprintf("%c", 39)) {
                if (length(v) < 2 || substr(v, length(v), 1) != q) next
                v = substr(v, 2, length(v) - 2)
            } else {
                if (v ~ /[^a-zA-Z0-9_.-]/) next
                q = ""
            }
            resultado = ""
            for (i = 1; i <= length(v); i++) {
                c = substr(v, i, 1)
                if (q == "\"" && c == "\\" && i < length(v)) {
                    n = substr(v, i + 1, 1)
                    if (n == "\\" || n == "\"" || n == "$" || n == sprintf("%c", 96)) {
                        c = n
                        i++
                    }
                }
                resultado = resultado c
            }
            valor = resultado
        }
        END { print valor }
    ' "$1"
}
familia() {
    case "$1" in
        ubuntu) echo UBUNTU ;;
        debian) echo DEBIAN ;;
        fedora) echo FEDORA ;;
        rhel|centos|rocky|almalinux|ol|redhat) echo REDHAT ;;
        suse|sles|sled|opensuse|opensuse-leap|opensuse-tumbleweed) echo SUSE ;;
        arch|archarm|manjaro) echo ARCH ;;
        gentoo) echo GENTOO ;;
        ututo) echo UTUTO ;;
        alpine) echo ALPINE ;;
        void) echo VOID ;;
        slackware) echo SLACKWARE ;;
        slax) echo Slax ;;
        mandriva|openmandriva) echo MANDRIVA ;;
        mandrake) echo MANDRAKE ;;
        antix) echo ANTIX ;;
        solus) echo SOLUS ;;
        pclinuxos) echo PCLINUXOS ;;
        gobolinux) echo GOBOLINUX ;;
        yellowdog) echo YELLOWDOG ;;
    esac
}
archivo_os="$raiz/etc/os-release"
if [ ! -e "$archivo_os" ] && [ ! -L "$archivo_os" ]; then
    archivo_os="$raiz/usr/lib/os-release"
fi
codigo=
nombre=
revision=
kernel=$(uname -s) || exit 1
case "$kernel" in
    Linux|GNU|GNU/kFreeBSD)
        id=$(campo "$archivo_os" ID)
        semejantes=$(campo "$archivo_os" ID_LIKE)
        nombre=$(campo "$archivo_os" VERSION_CODENAME)
        revision=$(campo "$archivo_os" VERSION_ID)
        codigo=$(familia "$id")
        if [ -z "$codigo" ]; then
            for candidato in $semejantes; do
                codigo=$(familia "$candidato")
                [ -z "$codigo" ] || break
            done
        fi
        if [ -z "$codigo" ] && [ -z "$id" ]; then
            lsb="$raiz/etc/lsb-release"
            lsb_id=$(campo "$lsb" DISTRIB_ID | tr '[:upper:]' '[:lower:]')
            codigo=$(familia "$lsb_id")
            [ -n "$nombre" ] || nombre=$(campo "$lsb" DISTRIB_CODENAME)
            [ -n "$revision" ] || revision=$(campo "$lsb" DISTRIB_RELEASE)
            if [ -z "$codigo" ]; then
                for par in ututo-release:UTUTO fedora-release:FEDORA redhat-release:REDHAT SuSE-release:SUSE mandriva-release:MANDRIVA mandrake-release:MANDRAKE arch-release:ARCH gentoo-release:GENTOO antiX:ANTIX alpine-release:ALPINE slax-version:Slax slackware-version:SLACKWARE debian_version:DEBIAN yellowdog-release:YELLOWDOG; do
                    if [ -f "$raiz/etc/${par%:*}" ]; then
                        codigo=${par#*:}
                        break
                    fi
                done
                if [ "$codigo" = DEBIAN ] && [ -r "$raiz/etc/issue" ]; then
                    if grep -qi Ubuntu "$raiz/etc/issue"; then codigo=UBUNTU
                    elif grep -qi elementary "$raiz/etc/issue"; then codigo=UBUNTU
                    fi
                fi
                if [ "$codigo" = REDHAT ] && [ -r "$raiz/etc/redhat-release" ]; then
                    [ -n "$nombre" ] || nombre=$(sed -n 's/.*(\([^)]*\)).*/\1/p' "$raiz/etc/redhat-release")
                    [ -n "$revision" ] || revision=$(sed -n 's/.*release \([0-9.]*\).*/\1/p' "$raiz/etc/redhat-release")
                fi
                if [ -z "$codigo" ]; then
                    if [ -f "$raiz/ututo.lastversion" ]; then codigo=UTUTO
                    elif [ -r "$raiz/etc/issue" ] && grep -qi ututo "$raiz/etc/issue"; then codigo=UTUTO
                    elif [ -r "$raiz/etc/profile" ] && grep -q SUSE "$raiz/etc/profile"; then codigo=SUSE
                    fi
                fi
            fi
        fi
        case "$kernel:$codigo" in
            GNU:DEBIAN) codigo=DEBIANGNUHURD ;;
            GNU:*) codigo=GNUHURD ;;
            GNU/kFreeBSD:*) codigo=DEBIANBSD ;;
            Linux:) codigo=OTHERGNULINUX ;;
        esac
        ;;
    Darwin)
        codigo=MACOSX
        if [ "$detalle" = 1 ] && command -v sw_vers >/dev/null 2>&1; then
            revision=$(sw_vers -productVersion 2>/dev/null)
        fi ;;
    FreeBSD) codigo=FREEBSD ;;
    OpenBSD) codigo=OPENBSD ;;
    NetBSD) codigo=NETBSD ;;
    DragonFly) codigo=DRAGONFLYBSD ;;
    MirBSD|MidnightBSD) codigo=MIRBSD ;;
    LibertyBSD) codigo=LIBERTYBSD ;;
    CYGWIN*) codigo=CYGWIN ;;
    MINGW*) codigo=MINGW ;;
    MSYS*) codigo=MSYS ;;
    SunOS|Solaris) codigo=SUNOS ;;
    AIX) codigo=AIX ;;
    Haiku) codigo=HAIKU ;;
    Minix|MINIX) codigo=MINIX ;;
    QNX*) codigo=QNX ;;
    IRIX*) codigo=IRIX ;;
    GNU*) codigo=GNUHURD ;;
    *) codigo=UNKNOWN ;;
esac
if [ "$detalle" = 1 ]; then
    salida=$codigo
    for parte in "$nombre" "$revision"; do
        parte=$(printf '%s' "$parte" | sed 's/[^a-zA-Z0-9_-]/_/g; s/__*/_/g; s/^_//; s/_$//')
        [ -z "$parte" ] || salida="${salida}_$parte"
    done
    printf '%s\n' "$salida"
else
    printf '%s\n' "$codigo"
fi
