#!/bin/sh
# ═══ RedRTOS — premier démarrage distribuable ═══
set -eu

RACINE_SYSTEME="${REDRTOS_RACINE_SYSTEME:-}"
ETAT="$RACINE_SYSTEME/var/lib/redrtos-premier-demarrage"
TRANSACTION="$ETAT/transaction"
DEFAUT="$RACINE_SYSTEME/etc/default_user"
TERMINE="$ETAT/termine"
NOM=redrtos
NOM_AFFICHE=RedRTOS
MOT_DE_PASSE=1234

echouer()
{
	printf 'Erreur premier démarrage : %s\n' "$1" >&2
	exit 1
}

nom_systeme_valide()
{
	CANDIDAT_NOM=$1
	case "$CANDIDAT_NOM" in
	[a-z_]*) ;;
	*) return 1 ;;
	esac
	case "$CANDIDAT_NOM" in
	*[!a-z0-9_-]*) return 1 ;;
	esac
	[ "${#CANDIDAT_NOM}" -le 31 ]
}

home_systeme_valide()
{
	case "$1" in
	/home/*) CANDIDAT_HOME=${1#/home/} ;;
	*) return 1 ;;
	esac
	case "$CANDIDAT_HOME" in
	""|*/*|.|..) return 1 ;;
	esac
	nom_systeme_valide "$CANDIDAT_HOME"
}

modifier_groupe()
{
	if [ -n "$RACINE_SYSTEME" ]
	then
		groupmod -R "$RACINE_SYSTEME" "$@"
	else
		groupmod "$@"
	fi
}

modifier_utilisateur()
{
	if [ -n "$RACINE_SYSTEME" ]
	then
		usermod -R "$RACINE_SYSTEME" "$@"
	else
		usermod "$@"
	fi
}

poser_mot_de_passe()
{
	if [ -n "$RACINE_SYSTEME" ]
	then
		chpasswd -c SHA512 -R "$RACINE_SYSTEME"
	else
		chpasswd -c SHA512
	fi
}

finaliser()
{
	systemctl daemon-reload
	TEMPORAIRE="$ETAT/.termine.$$"
	printf 'ok\n' > "$TEMPORAIRE"
	chmod 600 "$TEMPORAIRE"
	mv "$TEMPORAIRE" "$TERMINE"
}

compte_uid()
{
	awk -F: '$3 == 10000 {print $1}' "$RACINE_SYSTEME/etc/passwd"
}

groupe_gid()
{
	awk -F: '$3 == 10000 {print $1}' "$RACINE_SYSTEME/etc/group"
}

home_uid()
{
	awk -F: '$3 == 10000 {print $6}' "$RACINE_SYSTEME/etc/passwd"
}

[ ! -e "$TERMINE" ] || exit 0
mkdir -p "$ETAT"
chmod 700 "$ETAT"
[ ! -e "$DEFAUT" ] || {
	finaliser
	exit 0
}

UTILISATEUR=$(compte_uid)
GROUPE=$(groupe_gid)
HOME_ACTUEL=$(home_uid)
[ "$(awk -F: '$3 == 10000 {n++} END {print n + 0}' "$RACINE_SYSTEME/etc/passwd")" -eq 1 ] \
	|| echouer "état incohérent : UID 10000 absent ou dupliqué"
[ "$(awk -F: '$3 == 10000 {n++} END {print n + 0}' "$RACINE_SYSTEME/etc/group")" -eq 1 ] \
	|| echouer "état incohérent : GID 10000 absent ou dupliqué"
home_systeme_valide "$HOME_ACTUEL" \
	|| echouer "état incohérent : dossier personnel déclaré invalide"

if awk -F: -v nom="$NOM" '$1 == nom && $3 != 10000 {trouve=1} END {exit !trouve}' \
	"$RACINE_SYSTEME/etc/passwd"
then
	echouer "le nom $NOM appartient déjà à un autre compte"
fi
if awk -F: -v nom="$NOM" '$1 == nom && $3 != 10000 {trouve=1} END {exit !trouve}' \
	"$RACINE_SYSTEME/etc/group"
then
	echouer "le nom $NOM appartient déjà à un autre groupe"
fi

if [ -f "$TRANSACTION" ]
then
	[ "$(wc -l < "$TRANSACTION")" -eq 2 ] \
		|| echouer "état incohérent : transaction illisible"
	NOM_TRANSACTION=$(sed -n '1p' "$TRANSACTION")
	HOME_TRANSACTION=$(sed -n '2p' "$TRANSACTION")
	nom_systeme_valide "$NOM_TRANSACTION" \
		|| echouer "état incohérent : nom de transaction invalide"
	home_systeme_valide "$HOME_TRANSACTION" \
		|| echouer "état incohérent : dossier de transaction invalide"
	HOME_ORIGINE=""
	for CANDIDAT_HOME in "$HOME_ACTUEL" "/home/$NOM_TRANSACTION" "$HOME_TRANSACTION"
	do
		[ -e "$RACINE_SYSTEME$CANDIDAT_HOME" ] || continue
		if [ -n "$HOME_ORIGINE" ] && [ "$HOME_ORIGINE" != "$CANDIDAT_HOME" ]
		then
			echouer "état incohérent : plusieurs dossiers personnels possibles"
		fi
		HOME_ORIGINE=$CANDIDAT_HOME
	done
	[ -n "$HOME_ORIGINE" ] \
		|| echouer "état incohérent : dossier personnel introuvable"
else
	HOME_ORIGINE=$HOME_ACTUEL
	[ -e "$RACINE_SYSTEME$HOME_ORIGINE" ] \
		|| echouer "état incohérent : dossier personnel introuvable"
fi
TEMPORAIRE="$ETAT/transaction.$$"
printf '%s\n%s\n' "$NOM" "$HOME_ORIGINE" > "$TEMPORAIRE"
chmod 600 "$TEMPORAIRE"
mv "$TEMPORAIRE" "$TRANSACTION"

NOUVEAU_HOME="/home/$NOM"
if [ "$GROUPE" != "$NOM" ]
then
	modifier_groupe -n "$NOM" "$GROUPE"
fi
if [ "$UTILISATEUR" != "$NOM" ]
then
	modifier_utilisateur -l "$NOM" "$UTILISATEUR"
fi
modifier_utilisateur -c "$NOM_AFFICHE" "$NOM"

if [ "$HOME_ORIGINE" != "$NOUVEAU_HOME" ]
then
	if [ -e "$RACINE_SYSTEME$HOME_ORIGINE" ] && [ ! -e "$RACINE_SYSTEME$NOUVEAU_HOME" ]
	then
		mv "$RACINE_SYSTEME$HOME_ORIGINE" "$RACINE_SYSTEME$NOUVEAU_HOME"
	elif [ -e "$RACINE_SYSTEME$HOME_ORIGINE" ] || [ ! -e "$RACINE_SYSTEME$NOUVEAU_HOME" ]
	then
		echouer "état incohérent : déplacement du dossier personnel impossible"
	fi
fi

if [ "$(home_uid)" != "$NOUVEAU_HOME" ]
then
	modifier_utilisateur -d "$NOUVEAU_HOME" "$NOM"
fi

printf '%s:%s\n' "$NOM" "$MOT_DE_PASSE" | poser_mot_de_passe
unset MOT_DE_PASSE
rm -f "$RACINE_SYSTEME$NOUVEAU_HOME/.ssh/authorized_keys"

[ "$(compte_uid)" = "$NOM" ] || echouer "état incohérent : nom du compte final"
[ "$(groupe_gid)" = "$NOM" ] || echouer "état incohérent : nom du groupe final"
[ "$(home_uid)" = "$NOUVEAU_HOME" ] || echouer "état incohérent : dossier personnel final"
[ "$(awk -F: '$3 == 10000 {print $5}' "$RACINE_SYSTEME/etc/passwd")" = "$NOM_AFFICHE" ] \
	|| echouer "état incohérent : nom affiché final"
rm -f "$TRANSACTION"
TEMPORAIRE="$RACINE_SYSTEME/etc/.default_user.$$"
printf '%s\n' "$NOM" > "$TEMPORAIRE"
chmod 644 "$TEMPORAIRE"
mv "$TEMPORAIRE" "$DEFAUT"
finaliser
